]> git.openstreetmap.org Git - osqa.git/commitdiff
Creating my branch
authorhernani <hernani@0cfe37f9-358a-4d5e-be75-b63607b5c754>
Mon, 21 Feb 2011 17:38:02 +0000 (17:38 +0000)
committerhernani <hernani@0cfe37f9-358a-4d5e-be75-b63607b5c754>
Mon, 21 Feb 2011 17:38:02 +0000 (17:38 +0000)
git-svn-id: http://svn.osqa.net/svnroot/osqa/trunk@770 0cfe37f9-358a-4d5e-be75-b63607b5c754

538 files changed:
forum/modules/template_loader.py/.project [new file with mode: 0644]
forum/modules/template_loader.py/INSTALL [new file with mode: 0644]
forum/modules/template_loader.py/LICENSE [new file with mode: 0644]
forum/modules/template_loader.py/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/cron/README [new file with mode: 0644]
forum/modules/template_loader.py/cron/send_email_alerts [new file with mode: 0644]
forum/modules/template_loader.py/cron/send_email_alerts_virtualenv [new file with mode: 0644]
forum/modules/template_loader.py/forum/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/actions/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/actions/meta.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/actions/node.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/actions/page.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/actions/user.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/admin.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/authentication/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/authentication/base.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/badges/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/badges/base.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/context.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/feed.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/forms/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/forms/admin.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/forms/auth.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/forms/general.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/forms/qanda.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/http_responses.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/management/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/management/commands/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/management/commands/base_command.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/management/commands/checkinstall.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/management/commands/create_extended_user.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/management/commands/create_subscriptions.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/management/commands/message_to_everyone.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/management/commands/sample_command.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/management/commands/send_email_alerts.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/markdownext/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/markdownext/mdx_limitedsyntax.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/markdownext/mdx_settingsparser.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/markdownext/mdx_urlize.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/middleware/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/middleware/anon_user.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/middleware/cancel.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/middleware/extended_user.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/middleware/request_utils.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0001_initial.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0002_auto__add_likedcomment__del_field_repute_positive__del_field_repute_ne.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0003_repute_changes.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0004_auto__del_field_repute_negative__del_field_repute_positive__del_field_.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0005_fill_accepted_by_field.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0006_auto__add_node__add_field_vote_node__add_field_comment_node__add_field.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0007_q_and_a_to_node.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0008_auto__add_noderevision__del_field_vote_object_id__del_field_vote_conte.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0009_convert_revisions.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0010_auto__del_questionrevision__del_answerrevision__del_field_answer_vote_.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0011_auto__add_field_node_active_revision.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0012_set_active_revision.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0013_auto__del_anonymousquestion__del_anonymousanswer__add_anonymousnode.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0014_auto__add_field_question_accepted_answer.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0015_accepted_answer_changes.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0016_auto__del_field_question_answer_accepted__chg_field_question_node_ptr.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0017_auto__add_field_repute_node__add_field_repute_canceled.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0018_comments_to_node.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0019_auto__del_likedcomment__del_comment__add_field_node_abs_parent__chg_fi.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0020_create_absolute_parents.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0021_create_new_pg_fts_triggers.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0022_auto__add_actionrepute__add_action__add_favoritenode__del_field_node_v.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0023_flaten_node_inheritance_create_actions.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0024_auto__del_repute__del_vote__del_answer__del_flaggeditem__del_anonymous.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0025_auto__add_field_node_extra_action__add_field_node_deleted__add_field_n.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0026_reset_deleted_and_lastedited_flags.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0027_auto__del_activity.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0028_auto__add_field_action_canceled_ip__add_field_actionrepute_date.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0029_repute_dates.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0030_auto__chg_field_action_extra__chg_field_keyvalue_value.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0031_alter_pickle_storage.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0032_auto__del_field_user_hide_ignored_questions__del_field_user_questions_.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0033_auto__add_flag__add_vote__add_field_badge_cls__del_unique_badge_type_n.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0034_new_badge_and_award.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0035_auto__del_field_award_object_id__del_field_award_content_type__add_uni.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0036_auto__add_nodestate__chg_field_award_action__add_field_node_state_stri.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0037_fill_node_state.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0038_auto__del_field_node_wiki__del_field_node_deleted__del_field_node_extr.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0039_auto__del_field_tag_deleted__del_field_tag_deleted_by__del_field_tag_d.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0040_auto__chg_field_nodestate_action__add_field_node_extra.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0041_action_ip_fixes.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0042_auto__add_userproperty.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0043_auto__add_field_subscriptionsettings_send_digest__add_field_action_rea.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/0044_markdown_cache_migration.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/migrations/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/models/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/models/action.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/models/answer.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/models/base.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/models/comment.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/models/meta.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/models/node.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/models/page.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/models/question.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/models/tag.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/models/tests/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/models/tests/fixtures/users [new file with mode: 0644]
forum/modules/template_loader.py/forum/models/tests/test_user.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/models/user.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/models/utils.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/modules/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/modules/decorators.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/modules/template_loader.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/modules/ui.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/modules/ui_objects.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/registry.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/settings/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/settings/about.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/settings/accept.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/settings/base.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/settings/basic.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/settings/email.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/settings/extkeys.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/settings/faq.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/settings/form.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/settings/forms.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/settings/minrep.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/settings/moderation.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/settings/repgain.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/settings/sidebar.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/settings/static.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/settings/upload.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/settings/urls.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/settings/users.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/settings/view.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/settings/voting.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/sitemap.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/README [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/common/media/README [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/blue-up-arrow-h18px.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/box-arrow.gif [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/bullet_green.gif [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/by-sa-88x31.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/cc-88x31.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/cc-wiki.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/close-small-dark.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/close-small-hover.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/close-small.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/comment-delete-hover.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/comment-delete.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/comment-edit-hover.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/comment-edit.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/comment-like-on.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/comment-like.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/convert-hover.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/convert-off.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/dash.gif [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/djangomade124x25_grey.gif [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/dot-g.gif [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/dot-list.gif [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/edit.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/expander-arrow-hide.gif [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/expander-arrow-show.gif [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/favicon.gif [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/favicon.ico [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/feed-icon-small.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/gray-up-arrow-h18px.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/grippie.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/indicator.gif [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/logo.gif [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/logo.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/logo1.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/logo2.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/medala.gif [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/medala_on.gif [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/new.gif [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/nophoto.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/openid.gif [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/openid/aol.gif [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/openid/aol.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/openid/blogger.ico [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/openid/blogger.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/openid/claimid.ico [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/openid/claimid.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/openid/facebook.gif [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/openid/flickr.ico [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/openid/flickr.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/openid/google.gif [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/openid/livejournal.ico [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/openid/livejournal.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/openid/myopenid.ico [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/openid/myopenid.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/openid/myopenid_big.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/openid/openid-inputicon.gif [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/openid/openid.gif [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/openid/technorati.ico [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/openid/technorati.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/openid/twitter.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/openid/verisign.ico [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/openid/verisign.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/openid/vidoop.ico [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/openid/wordpress.ico [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/openid/wordpress.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/openid/yahoo.gif [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/quest-bg.gif [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/user-sprite.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/vote-accepted-on.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/vote-accepted.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/vote-arrow-down-on.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/vote-arrow-down.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/vote-arrow-up-on.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/vote-arrow-up.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/vote-favorite-off.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/vote-favorite-on.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/webfaction.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/images/wiki.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/compress.bat [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/effects.core.min.js [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/excanvas.min.js [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/flot-build.bat [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/jquery-1.2.6.js [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/jquery-1.2.6.min.js [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/jquery.ajaxfileupload.js [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/jquery.flot.js [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/jquery.flot.min.js [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/jquery.form.js [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/jquery.i18n.js [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/jquery.openid.js [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/jquery.validate.pack.js [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/osqa.admin.js [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/osqa.ask.js [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/osqa.main.js [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/osqa.main.min.js [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/osqa.question.js [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/se_hilite.js [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/se_hilite_src.js [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/ui.core.js [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/ui.core.min.js [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/ui.datepicker.js [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/ui.datepicker.min.js [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/bg-fill.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/bg.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/blockquote.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/bold.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/code.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/h1.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/hr.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/img.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/italic.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/link.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/ol.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/redo.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/separator.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/ul.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/undo.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/wmd-buttons.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/wmd-buttons.psd [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/wmd-on.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/wmd.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/wmd/showdown-min.js [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/wmd/showdown.js [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/wmd/wmd-min.js [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/wmd/wmd-test.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/wmd/wmd.css [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/wmd/wmd.js [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/js/yuicompressor-2.4.2.jar [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/style/admin.css [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/style/auth.css [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/style/default.css [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/style/djstyle_admin.css [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/style/jquery.autocomplete.css [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/style/markdown_help.css [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/style/openid.css [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/style/prettify.css [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/style/style.css [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/media/style/user.css [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/401.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/403.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/404.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/500.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/503.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/account_settings.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/answer_edit.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/answer_edit_tips.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/ask.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/auth/auth_settings.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/auth/complete.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/auth/mail_already_validated.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/auth/mail_validation.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/auth/signin.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/auth/temp_login_email.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/auth/temp_login_request.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/auth/welcome_email.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/badge.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/badges.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/base.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/base_content.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/close.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/edit_user_email_feeds_form.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/email_base.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/feedback.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/feeds/rss_answer_title.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/feeds/rss_description.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/feeds/rss_title.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/footer.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/header.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/index.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/logout.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/markdown_help.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/node/accept_button.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/node/comments.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/node/contributors_info.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/node/convert_to_comment.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/node/convert_to_question.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/node/favorite_mark.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/node/flagged_item.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/node/post_controls.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/node/report.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/node/reviser_info.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/node/revision.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/node/vote_buttons.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/node/wiki_symbol.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/notarobot.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/notifications/answeraccepted.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/notifications/base.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/notifications/base_text.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/notifications/digest.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/notifications/feedback.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/notifications/newanswer.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/notifications/newcomment.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/notifications/newmember.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/notifications/newquestion.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/opensearch.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/base.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/createuser.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/dashboard.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/djstyle_base.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/edit_page.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/flagged_posts.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/graph.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/index.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/maintenance.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/moderation.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/nodeman.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/set.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/static_pages.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/statistics.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/page.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/pagesize.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/paginator.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/paginator/page_numbers.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/paginator/page_sizes.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/paginator/sort_tabs.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/privacy.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/question.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/question_edit.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/question_edit_tips.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/question_list/count.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/question_list/item.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/question_list/related_tags.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/question_list/sort_tabs.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/question_list/subscription_item.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/question_list/tag_selector.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/question_list/title.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/question_retag.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/question_summary_list_roll.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/questions.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/reopen.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/revisions.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/search.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/sidebar/markdown_help.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/sidebar/recent_awards.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/sidebar/recent_tags.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/sidebar/user_blocks.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/static.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/subscription_status.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/tag_selector.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/tags.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/user.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/users/activity.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/users/edit.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/users/info.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/users/karma_bonus.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/users/menu.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/users/online_users.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/users/preferences.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/users/questions.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/users/recent.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/users/reputation.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/users/signature.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/users/stats.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/users/subscriptions.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/users/subscriptions_management.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/users/subscriptions_settings.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/users/suspend_user.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/users/tabs.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/users/users.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/skins/default/templates/users/votes.html [new file with mode: 0644]
forum/modules/template_loader.py/forum/startup.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/subscriptions.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/templatetags/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/templatetags/email_tags.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/templatetags/extra_filters.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/templatetags/extra_tags.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/templatetags/general_sidebar_tags.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/templatetags/node_tags.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/templatetags/question_list_tags.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/templatetags/smart_if.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/templatetags/ui_registry.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/templatetags/user_tags.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/upfiles/README [new file with mode: 0644]
forum/modules/template_loader.py/forum/upfiles/logo.png [new file with mode: 0644]
forum/modules/template_loader.py/forum/urls.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/user_messages/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/user_messages/context_processors.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/utils/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/utils/decorators.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/utils/diff.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/utils/djangofix.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/utils/html.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/utils/html2text.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/utils/lists.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/utils/mail.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/utils/pagination.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/utils/time.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/utils/userlinking.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/views/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/views/admin.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/views/auth.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/views/commands.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/views/decorators.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/views/meta.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/views/readers.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/views/users.py [new file with mode: 0644]
forum/modules/template_loader.py/forum/views/writers.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/akismet/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/akismet/lib/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/akismet/lib/akismet.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/akismet/settings.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/akismet/startup.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/akismet/templates/foundspam.html [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/default_badges/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/default_badges/badges.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/default_badges/settings.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/exporter/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/exporter/backups/README [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/exporter/commands.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/exporter/exporter.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/exporter/forms.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/exporter/importer.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/exporter/mappings.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/exporter/orm.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/exporter/settings.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/exporter/startup.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/exporter/templates/exporter.html [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/exporter/templates/importer.html [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/exporter/templates/running.html [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/exporter/tmp/README [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/exporter/urls.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/exporter/views.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/facebookauth/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/facebookauth/authentication.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/facebookauth/settings.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/facebookauth/templates/button.html [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/facebookauth/templates/xd_receiver.html [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/facebookauth/urls.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/facebookauth/views.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/localauth/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/localauth/authentication.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/localauth/forms.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/localauth/templates/loginform.html [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/localauth/urls.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/localauth/views.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/oauthauth/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/oauthauth/authentication.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/oauthauth/consumer.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/oauthauth/lib/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/oauthauth/lib/oauth.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/oauthauth/settings.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/openidauth/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/openidauth/authentication.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/openidauth/consumer.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/openidauth/models.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/openidauth/settings.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/openidauth/store.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/openidauth/templates/openidurl.html [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/pgfulltext/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/pgfulltext/handlers.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/pgfulltext/pg_fts_install.sql [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/pgfulltext/settings.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/pgfulltext/startup.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/project_badges/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/project_badges/badges.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/project_badges/settings.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/recaptcha/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/recaptcha/formfield.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/recaptcha/handlers.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/recaptcha/lib/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/recaptcha/lib/captcha.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/recaptcha/settings.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/robotstxt/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/robotstxt/settings.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/robotstxt/templates/robots.txt [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/robotstxt/urls.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/sphinxfulltext/README.txt [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/sphinxfulltext/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/sphinxfulltext/dependencies.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/sphinxfulltext/handlers.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/sphinxfulltext/models.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/sphinxfulltext/settings.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/sximporter/__init__.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/sximporter/importer.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/sximporter/orm.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/sximporter/templates/page.html [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/sximporter/urls.py [new file with mode: 0644]
forum/modules/template_loader.py/forum_modules/sximporter/views.py [new file with mode: 0644]
forum/modules/template_loader.py/locale/bg/LC_MESSAGES/django.mo [new file with mode: 0755]
forum/modules/template_loader.py/locale/bg/LC_MESSAGES/django.po [new file with mode: 0755]
forum/modules/template_loader.py/locale/de/LC_MESSAGES/django.mo [new file with mode: 0644]
forum/modules/template_loader.py/locale/de/LC_MESSAGES/django.po [new file with mode: 0644]
forum/modules/template_loader.py/locale/en/LC_MESSAGES/django.mo [new file with mode: 0644]
forum/modules/template_loader.py/locale/en/LC_MESSAGES/django.po [new file with mode: 0644]
forum/modules/template_loader.py/locale/es/LC_MESSAGES/django.mo [new file with mode: 0644]
forum/modules/template_loader.py/locale/es/LC_MESSAGES/django.po [new file with mode: 0644]
forum/modules/template_loader.py/locale/fr/LC_MESSAGES/django.mo [new file with mode: 0644]
forum/modules/template_loader.py/locale/fr/LC_MESSAGES/django.po [new file with mode: 0644]
forum/modules/template_loader.py/locale/l/LC_MESSAGES/django.mo [new file with mode: 0644]
forum/modules/template_loader.py/locale/l/LC_MESSAGES/django.po [new file with mode: 0644]
forum/modules/template_loader.py/locale/phrases.py [new file with mode: 0644]
forum/modules/template_loader.py/locale/pt/LC_MESSAGES/django.mo [new file with mode: 0644]
forum/modules/template_loader.py/locale/pt/LC_MESSAGES/django.po [new file with mode: 0644]
forum/modules/template_loader.py/locale/zh_CN/LC_MESSAGES/django.mo [new file with mode: 0644]
forum/modules/template_loader.py/locale/zh_CN/LC_MESSAGES/django.po [new file with mode: 0644]
forum/modules/template_loader.py/log/README.TXT [new file with mode: 0644]
forum/modules/template_loader.py/manage.py [new file with mode: 0644]
forum/modules/template_loader.py/osqa.iml [new file with mode: 0644]
forum/modules/template_loader.py/osqa.wsgi.dist [new file with mode: 0644]
forum/modules/template_loader.py/rmpyc [new file with mode: 0644]
forum/modules/template_loader.py/settings.py [new file with mode: 0644]
forum/modules/template_loader.py/settings_local.py.dist [new file with mode: 0644]
forum/modules/template_loader.py/tmp/README [new file with mode: 0644]
forum/modules/template_loader.py/urls.py [new file with mode: 0644]

diff --git a/forum/modules/template_loader.py/.project b/forum/modules/template_loader.py/.project
new file mode 100644 (file)
index 0000000..5b1b909
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>osqa-pydev</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.wst.jsdt.core.javascriptValidator</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.python.pydev.PyDevBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.python.pydev.pythonNature</nature>
+               <nature>org.eclipse.wst.jsdt.core.jsNature</nature>
+               <nature>org.python.pydev.django.djangoNature</nature>
+       </natures>
+</projectDescription>
diff --git a/forum/modules/template_loader.py/INSTALL b/forum/modules/template_loader.py/INSTALL
new file mode 100644 (file)
index 0000000..525947b
--- /dev/null
@@ -0,0 +1,5 @@
+For installation instruction go to:
+
+http://wiki.osqa.net/display/docs/Home
+
+The wiki contains many recipes to help you install on different hosting providers.
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/LICENSE b/forum/modules/template_loader.py/LICENSE
new file mode 100644 (file)
index 0000000..de192e0
--- /dev/null
@@ -0,0 +1,15 @@
+Copyright (c) 2010. OSQA
+Some portions Copyright (c) 2009 Chen Gang
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+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 --git a/forum/modules/template_loader.py/__init__.py b/forum/modules/template_loader.py/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/forum/modules/template_loader.py/cron/README b/forum/modules/template_loader.py/cron/README
new file mode 100644 (file)
index 0000000..d557315
--- /dev/null
@@ -0,0 +1,5 @@
+this directory contains sample commands to be executed
+by cron 
+
+files with names ending "virtuanenv" should work under Python virtualenv system
+other files - with standard unix setup
diff --git a/forum/modules/template_loader.py/cron/send_email_alerts b/forum/modules/template_loader.py/cron/send_email_alerts
new file mode 100644 (file)
index 0000000..cae0960
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/sh
+PYTHONPATH=/path/to/dir_above_osqa_site
+export PYTHONPATH
+PROJECT_ROOT=$PYTHONPATH/osqa_site
+/path/to/python $PROJECT_ROOT/manage.py send_email_alerts
diff --git a/forum/modules/template_loader.py/cron/send_email_alerts_virtualenv b/forum/modules/template_loader.py/cron/send_email_alerts_virtualenv
new file mode 100644 (file)
index 0000000..6c9e154
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+WORKON_HOME=~/envs/osqa
+PROJECT_ROOT=~/webapps/osqa_server/projects/osqa/
+
+# activate virtual environment
+. $WORKON_HOME/bin/activate
+
+cd $PROJECT_ROOT
+python manage.py send_email_alerts >> $PROJECT_ROOT/log/cron_mail.log 2>&1
diff --git a/forum/modules/template_loader.py/forum/__init__.py b/forum/modules/template_loader.py/forum/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/forum/modules/template_loader.py/forum/actions/__init__.py b/forum/modules/template_loader.py/forum/actions/__init__.py
new file mode 100644 (file)
index 0000000..4c6c678
--- /dev/null
@@ -0,0 +1,4 @@
+from meta import *\r
+from node import *\r
+from user import *\r
+from page import *
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/actions/meta.py b/forum/modules/template_loader.py/forum/actions/meta.py
new file mode 100644 (file)
index 0000000..f5c12cd
--- /dev/null
@@ -0,0 +1,215 @@
+from django.utils.translation import ugettext as _\r
+from django.db.models import F\r
+from forum.models.action import ActionProxy, DummyActionProxy\r
+from forum.models import Vote, Flag\r
+from forum import settings\r
+\r
+class VoteAction(ActionProxy):\r
+    def update_node_score(self, inc):\r
+        self.node.score = F('score') + inc\r
+        self.node.save()\r
+\r
+    def process_vote_action(self, value):\r
+        self.update_node_score(value)\r
+        vote = Vote(node=self.node, user=self.user, action=self, value=value)\r
+        vote.save()\r
+\r
+    def cancel_action(self):\r
+        vote = self.vote\r
+        self.update_node_score(-vote.value)\r
+        vote.delete()\r
+\r
+    @classmethod\r
+    def get_for(cls, user, node):\r
+        try:\r
+            vote = Vote.objects.get(user=user, node=node)\r
+            return vote.value\r
+        except:\r
+            return None\r
+\r
+    @classmethod\r
+    def get_action_for(cls, user, node):\r
+        try:\r
+            vote = Vote.objects.get(user=user, node=node)\r
+            return vote.action\r
+        except:\r
+            return None\r
+\r
+    def describe_vote(self, vote_desc, viewer=None):\r
+        return _("%(user)s %(vote_desc)s %(post_desc)s") % {\r
+            'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),\r
+            'vote_desc': vote_desc, 'post_desc': self.describe_node(viewer, self.node)\r
+        }\r
+\r
+\r
+class VoteUpAction(VoteAction):\r
+    def repute_users(self):\r
+        self.repute(self.node.author, int(settings.REP_GAIN_BY_UPVOTED))\r
+\r
+    def process_action(self):\r
+        self.process_vote_action(1)\r
+        self.user.reset_vote_up_count_cache()\r
+\r
+    def cancel_action(self):\r
+        super(VoteUpAction, self).cancel_action()\r
+        self.user.reset_vote_up_count_cache()\r
+\r
+    def describe(self, viewer=None):\r
+        return self.describe_vote(_("voted up"), viewer)\r
+\r
+class VoteDownAction(VoteAction):\r
+    def repute_users(self):\r
+        self.repute(self.node.author, -int(settings.REP_LOST_BY_DOWNVOTED))\r
+        self.repute(self.user, -int(settings.REP_LOST_BY_DOWNVOTING))\r
+\r
+    def process_action(self):\r
+        self.process_vote_action(-1)\r
+        self.user.reset_vote_down_count_cache()\r
+\r
+    def cancel_action(self):\r
+        super(VoteDownAction, self).cancel_action()\r
+        self.user.reset_vote_down_count_cache()\r
+\r
+    def describe(self, viewer=None):\r
+        return self.describe_vote(_("voted down"), viewer)\r
+\r
+\r
+class VoteUpCommentAction(VoteUpAction):\r
+    def repute_users(self):\r
+        pass\r
+\r
+    def process_action(self):\r
+        self.process_vote_action(1)\r
+\r
+    def cancel_action(self):\r
+        super(VoteUpAction, self).cancel_action()\r
+\r
+    def describe(self, viewer=None):\r
+        return self.describe_vote(_("liked"), viewer)\r
+\r
+\r
+class FlagAction(ActionProxy):\r
+    def repute_users(self):\r
+        self.repute(self.node.author, -int(settings.REP_LOST_BY_FLAGGED))\r
+\r
+    def process_action(self):\r
+        flag = Flag(user=self.user, node=self.node, action=self, reason=self.extra)\r
+        flag.save()\r
+        self.node.reset_flag_count_cache()\r
+\r
+        if self.node.flag_count == int(settings.FLAG_COUNT_TO_HIDE_POST):\r
+            self.repute(self.node.author, -int(settings.REP_LOST_BY_FLAGGED_3_TIMES))\r
+\r
+        if self.node.flag_count == int(settings.FLAG_COUNT_TO_DELETE_POST):\r
+            self.repute(self.node.author, -int(settings.REP_LOST_BY_FLAGGED_5_TIMES))\r
+            if not self.node.nis.deleted:\r
+                DeleteAction(node=self.node, user=self.user, extra="BYFLAGGED").save()\r
+\r
+    def cancel_action(self):\r
+        self.flag.delete()\r
+        self.node.reset_flag_count_cache()\r
+\r
+    @classmethod\r
+    def get_for(cls, user, node):\r
+        try:\r
+            flag = Flag.objects.get(user=user, node=node)\r
+            return flag.reason or _("No reason given")\r
+        except:\r
+            return None\r
+\r
+    def describe(self, viewer=None):\r
+        return _("%(user)s flagged %(post_desc)s: %(reason)s") % {\r
+            'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),\r
+            'post_desc': self.describe_node(viewer, self.node), 'reason': self.extra\r
+        }\r
+\r
+\r
+class AcceptAnswerAction(ActionProxy):\r
+    def repute_users(self):\r
+        if (self.user == self.node.parent.author) and (not self.user == self.node.author):\r
+            self.repute(self.user, int(settings.REP_GAIN_BY_ACCEPTING))\r
+\r
+        if self.user != self.node.author:\r
+            self.repute(self.node.author, int(settings.REP_GAIN_BY_ACCEPTED))\r
+\r
+    def process_action(self):\r
+        self.node.marked = True\r
+        self.node.nstate.accepted = self\r
+        self.node.save()\r
+        self.node.question.reset_accepted_count_cache()\r
+\r
+    def cancel_action(self):\r
+        self.node.marked = False\r
+        self.node.nstate.accepted = None\r
+        self.node.save()\r
+        self.node.question.reset_accepted_count_cache()\r
+\r
+    def describe(self, viewer=None):\r
+        answer = self.node\r
+        question = answer.parent\r
+\r
+        if self.user == question.author:\r
+            asker = (self.user == viewer) and _("your") or _("his")\r
+        else:\r
+            asker = self.hyperlink(question.author.get_profile_url(), question.author.username)\r
+\r
+        return _("%(user)s accepted %(answerer)s answer on %(asker)s question %(question)s") % {\r
+            'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),\r
+            'answerer': self.hyperlink(answer.author.get_profile_url(), self.friendly_ownername(viewer, answer.author)),\r
+            'asker': asker,\r
+            'question': self.hyperlink(question.get_absolute_url(), question.title)\r
+        }\r
+\r
+\r
+class FavoriteAction(ActionProxy):\r
+    def process_action(self):\r
+        self.node.reset_favorite_count_cache()\r
+\r
+    def cancel_action(self):\r
+        self.process_action()\r
+\r
+    def describe(self, viewer=None):\r
+        return _("%(user)s marked %(post_desc)s as favorite") % {\r
+            'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),\r
+            'post_desc': self.describe_node(viewer, self.node),\r
+        }\r
+\r
+\r
+class DeleteAction(ActionProxy):\r
+    def process_action(self):\r
+        self.node.mark_deleted(self)\r
+        \r
+        if self.node.node_type == "answer":\r
+            self.node.question.reset_answer_count_cache()\r
+\r
+    def cancel_action(self):\r
+        self.node.mark_deleted(None)\r
+\r
+        if self.node.node_type == "answer":\r
+            self.node.question.reset_answer_count_cache()\r
+\r
+    def describe(self, viewer=None):\r
+        return _("%(user)s deleted %(post_desc)s") % {\r
+            'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),\r
+            'post_desc': self.describe_node(viewer, self.node)\r
+        }\r
+\r
+    def reason(self):\r
+        if self.extra != "BYFLAGGED":\r
+            return self.extra\r
+        else:\r
+            return _("flagged by multiple users: ") + "; ".join([f.extra for f in FlagAction.objects.filter(node=self.node)])\r
+\r
+class UnknownAction(ActionProxy):\r
+    pass\r
+\r
+\r
+class QuestionViewAction(DummyActionProxy):\r
+    def __init__(self, node, user, ip=None):\r
+        self.viewuser = user\r
+        self.node = node\r
+        super(QuestionViewAction, self).__init__(ip)\r
+\r
+    def process_action(self):\r
+        self.node.extra_count = F('extra_count') + 1\r
+        self.node.save()\r
diff --git a/forum/modules/template_loader.py/forum/actions/node.py b/forum/modules/template_loader.py/forum/actions/node.py
new file mode 100644 (file)
index 0000000..cd39924
--- /dev/null
@@ -0,0 +1,236 @@
+from django.utils.html import strip_tags\r
+from django.utils.translation import ugettext as _\r
+from forum.models.action import ActionProxy\r
+from forum.models import Comment, Question, Answer, NodeRevision\r
+\r
+class NodeEditAction(ActionProxy):\r
+    def create_revision_data(self, initial=False, **data):\r
+        revision_data = dict(summary=data.get('summary', (initial and _('Initial revision') or '')), body=data['text'])\r
+\r
+        if data.get('title', None):\r
+            revision_data['title'] = strip_tags(data['title'].strip())\r
+\r
+        if data.get('tags', None):\r
+            revision_data['tagnames'] = data['tags'].strip()\r
+\r
+        return revision_data\r
+\r
+class AskAction(NodeEditAction):\r
+    verb = _("asked")\r
+\r
+    def process_data(self, **data):\r
+        processed_data = self.create_revision_data(True, **data)\r
+        if 'added_at' in data:\r
+            processed_data['added_at'] = data['added_at']\r
+\r
+        question = Question(author=self.user, **processed_data)\r
+        question.save()\r
+        self.node = question\r
+\r
+    def describe(self, viewer=None):\r
+        return _("%(user)s asked %(question)s") % {\r
+            'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),\r
+            'question': self.hyperlink(self.node.get_absolute_url(), self.node.title)\r
+        }\r
+\r
+class AnswerAction(NodeEditAction):\r
+    verb = _("answered")\r
+\r
+    def process_data(self, **data):\r
+        answer = Answer(author=self.user, parent=data['question'], **self.create_revision_data(True, **data))\r
+        answer.save()\r
+        self.node = answer\r
+\r
+    def process_action(self):\r
+        self.node.question.reset_answer_count_cache()\r
+\r
+    def describe(self, viewer=None):\r
+        question = self.node.parent\r
+        return _("%(user)s answered %(asker)s on %(question)s") % {\r
+            'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),\r
+            'asker': self.hyperlink(question.author.get_profile_url(), self.friendly_username(viewer, question.author)),\r
+            'question': self.hyperlink(self.node.get_absolute_url(), question.title)\r
+        }\r
+\r
+class CommentAction(ActionProxy):\r
+    verb = _("commented")\r
+\r
+    def process_data(self, text='', parent=None):\r
+        comment = Comment(author=self.user, parent=parent, body=text)\r
+        comment.save()\r
+        self.node = comment\r
+\r
+    def describe(self, viewer=None):\r
+        return _("%(user)s commented on %(post_desc)s") % {\r
+            'user': self.hyperlink(self.node.author.get_profile_url(), self.friendly_username(viewer, self.node.author)),\r
+            'post_desc': self.describe_node(viewer, self.node.parent)\r
+        }\r
+\r
+class ReviseAction(NodeEditAction):\r
+    verb = _("edited")\r
+\r
+    def process_data(self, **data):\r
+        revision_data = self.create_revision_data(**data)\r
+        revision = self.node.create_revision(self.user, **revision_data)\r
+        self.extra = revision.revision\r
+\r
+    def process_action(self):\r
+        self.node.last_edited = self\r
+        self.node.save()\r
+\r
+    def describe(self, viewer=None):\r
+        return _("%(user)s edited %(post_desc)s") % {\r
+            'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),\r
+            'post_desc': self.describe_node(viewer, self.node)\r
+        }\r
+\r
+    def get_absolute_url(self):\r
+        return self.node.get_revisions_url()\r
+\r
+class RetagAction(ActionProxy):\r
+    verb = _("retagged")\r
+\r
+    def process_data(self, tagnames=''):\r
+        active = self.node.active_revision\r
+        revision_data = dict(summary=_('Retag'), title=active.title, tagnames=strip_tags(tagnames.strip()), body=active.body)\r
+        revision = self.node.create_revision(self.user, **revision_data)\r
+        self.extra = revision.revision\r
+\r
+    def process_action(self):\r
+        self.node.last_edited = self\r
+        self.node.save()\r
+\r
+    def describe(self, viewer=None):\r
+        return _("%(user)s retagged %(post_desc)s") % {\r
+            'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),\r
+            'post_desc': self.describe_node(viewer, self.node)\r
+        }\r
+\r
+    def get_absolute_url(self):\r
+        return self.node.get_revisions_url()\r
+\r
+class RollbackAction(ActionProxy):\r
+    verb = _("reverted")\r
+\r
+    def process_data(self, activate=None):\r
+        previous = self.node.active_revision\r
+        self.node.activate_revision(self.user, activate)\r
+        self.extra = "%d:%d" % (previous.revision, activate.revision)\r
+\r
+    def process_action(self):\r
+        self.node.last_edited = self\r
+        self.node.save()\r
+\r
+    def describe(self, viewer=None):\r
+        revisions = [NodeRevision.objects.get(node=self.node, revision=int(n)) for n in self.extra.split(':')]\r
+\r
+        return _("%(user)s reverted %(post_desc)s from revision %(initial)d (%(initial_sum)s) to revision %(final)d (%(final_sum)s)") % {\r
+            'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),\r
+            'post_desc': self.describe_node(viewer, self.node),\r
+            'initial': revisions[0].revision, 'initial_sum': revisions[0].summary,\r
+            'final': revisions[1].revision, 'final_sum': revisions[1].summary,\r
+        }\r
+\r
+    def get_absolute_url(self):\r
+        return self.node.get_revisions_url()\r
+\r
+class CloseAction(ActionProxy):\r
+    verb = _("closed")\r
+\r
+    def process_action(self):\r
+        self.node.marked = True\r
+        self.node.nstate.closed = self\r
+        self.node.last_edited = self\r
+        self.node.update_last_activity(self.user, save=True)\r
+\r
+    def cancel_action(self):\r
+        self.node.marked = False\r
+        self.node.nstate.closed = None\r
+        self.node.update_last_activity(self.user, save=True)\r
+\r
+    def describe(self, viewer=None):\r
+        return _("%(user)s closed %(post_desc)s: %(reason)s") % {\r
+            'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),\r
+            'post_desc': self.describe_node(viewer, self.node),\r
+            'reason': self.extra\r
+        }\r
+\r
+class AnswerToCommentAction(ActionProxy):\r
+    verb = _("converted")\r
+\r
+    def process_data(self, new_parent=None):\r
+        self.node.parent = new_parent\r
+        self.node.node_type = "comment"\r
+\r
+        for comment in self.node.comments.all():\r
+            comment.parent = new_parent\r
+            comment.save()\r
+\r
+        self.node.last_edited = self\r
+        self.node.update_last_activity(self.user, save=True)\r
+        try:\r
+            self.node.abs_parent.reset_answer_count_cache()\r
+        except AttributeError:\r
+            pass\r
+\r
+    def describe(self, viewer=None):\r
+        return _("%(user)s converted an answer to %(question)s into a comment") % {\r
+            'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),\r
+            'question': self.describe_node(viewer, self.node.abs_parent),\r
+        }\r
+\r
+class CommentToAnswerAction(ActionProxy):\r
+    verb = _("converted")\r
+\r
+    def process_data(self, question):\r
+        self.node.parent = question\r
+        self.node.node_type = "answer"\r
+        self.node.last_edited = self\r
+        self.node.update_last_activity(self.user, save=True)\r
+\r
+\r
+    def describe(self, viewer=None):\r
+        return _("%(user)s converted comment on %(question)s into an answer") % {\r
+            'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),\r
+            'question': self.describe_node(viewer, self.node.abs_parent),\r
+        }\r
+\r
+class AnswerToQuestionAction(ActionProxy):\r
+    verb = _("converted to question")\r
+\r
+    def process_data(self, title):\r
+        self.node.node_type = "question"\r
+        self.node.title = title\r
+        self.node.last_edited = self\r
+        self.node.update_last_activity(self.user, save=True)\r
+\r
+        try:\r
+            self.node.abs_parent.reset_answer_count_cache()\r
+        except AttributeError:\r
+            pass\r
+\r
+\r
+    def describe(self, viewer=None):\r
+        return _("%(user)s converted an answer to %(question)s into a separate question") % {\r
+            'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),\r
+            'question': self.describe_node(viewer, self.node.abs_parent),\r
+        }\r
+\r
+class WikifyAction(ActionProxy):\r
+    verb = _("wikified")\r
+\r
+    def process_action(self):\r
+        self.node.nstate.wiki = self\r
+        self.node.last_edited = self\r
+        self.node.update_last_activity(self.user, save=True)\r
+\r
+    def cancel_action(self):\r
+        self.node.nstate.wiki = None\r
+        self.node.update_last_activity(self.user, save=True)\r
+\r
+    def describe(self, viewer=None):\r
+        return _("%(user)s marked %(node)s as community wiki.") % {\r
+            'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),\r
+            'node': self.describe_node(viewer, self.node),\r
+        }\r
+\r
diff --git a/forum/modules/template_loader.py/forum/actions/page.py b/forum/modules/template_loader.py/forum/actions/page.py
new file mode 100644 (file)
index 0000000..508e8c2
--- /dev/null
@@ -0,0 +1,58 @@
+from django.utils.translation import ugettext as _
+from forum.models.action import ActionProxy
+from forum.models import Page
+
+class NewPageAction(ActionProxy):
+    verb = _("created")
+
+    def process_data(self, **data):
+        title = data.pop('title')
+        body = data.pop('content')
+
+        page = Page(author=self.user, title=title, body=body, extra=data)
+        page.save()
+        self.node = page
+
+    def describe(self, viewer=None):
+        return _("%(user)s created a new page titled %(page)s") % {
+        'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
+        'page': self.hyperlink(self.node.get_absolute_url(), self.node.title)
+        }
+
+class EditPageAction(ActionProxy):
+    verb = _("edited")
+
+    def process_data(self, **data):
+        title = data.pop('title')
+        body = data.pop('content')
+
+        if (title != self.node.title) or (body != self.node.body):
+            self.node.create_revision(self.user, title=title, body=body)
+
+        self.node.extra = data
+        self.node.save()
+
+    def describe(self, viewer=None):
+        return _("%(user)s edited the page titled %(page)s") % {
+        'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
+        'page': self.hyperlink(self.node.get_absolute_url(), self.node.title)
+        }
+
+class PublishAction(ActionProxy):
+    verb = _("published")
+
+    def process_action(self):
+        self.node.marked = True
+        self.node.nstate.published = self
+        self.node.save()
+
+    def cancel_action(self):
+        self.node.marked = False
+        self.node.nstate.published = None
+        self.node.save()
+
+    def describe(self, viewer=None):
+        return _("%(user)s published a new page titled %(page)s") % {
+        'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
+        'page': self.hyperlink(self.node.get_absolute_url(), self.node.title)
+        }
diff --git a/forum/modules/template_loader.py/forum/actions/user.py b/forum/modules/template_loader.py/forum/actions/user.py
new file mode 100644 (file)
index 0000000..50d1a73
--- /dev/null
@@ -0,0 +1,161 @@
+from django.utils.translation import ugettext as _
+from django.db.models import F
+from forum.models.action import ActionProxy
+from forum.models import Award, Badge, ValidationHash, User
+from forum import settings
+from forum.settings import APP_SHORT_NAME
+from forum.utils.mail import send_template_email
+
+class UserJoinsAction(ActionProxy):
+    verb = _("joined")
+
+    def repute_users(self):
+        self.repute(self.user, int(settings.INITIAL_REP))
+
+    def process_action(self):
+        hash = ValidationHash.objects.create_new(self.user, 'email', [self.user.email])
+        send_template_email([self.user], "auth/welcome_email.html", {'validation_code': hash})
+
+    def describe(self, viewer=None):
+        return _("%(user)s %(have_has)s joined the %(app_name)s Q&A community") % {
+        'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
+        'have_has': self.viewer_or_user_verb(viewer, self.user, _('have'), _('has')),
+        'app_name': APP_SHORT_NAME,
+        }
+
+class EditProfileAction(ActionProxy):
+    verb = _("edited profile")
+
+    def describe(self, viewer=None):
+        return _("%(user)s edited %(hes_or_your)s %(profile_link)s") % {
+        'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
+        'hes_or_your': self.viewer_or_user_verb(viewer, self.user, _('your'), _('his')),
+        'profile_link': self.hyperlink(self.user.get_profile_url(), _('profile')),
+        }
+
+class BonusRepAction(ActionProxy):
+    verb = _("gave bonus")
+
+    def process_data(self, value, affected):
+        self._value = value
+        self._affected = affected
+
+
+    def repute_users(self):
+        self.repute(self._affected, self._value)
+
+        if self._value > 0:
+            self._affected.message_set.create(
+                    message=_("Congratulations, you have been awarded an extra %s reputation points.") % self._value +
+                    '<br />%s' % self.extra.get('message', _('Thank you')))
+        else:
+            self._affected.message_set.create(
+                    message=_("You have been penalized in %s reputation points.") % self._value +
+                    '<br />%s' % self.extra.get('message', ''))
+
+    def describe(self, viewer=None):
+        value = self.extra.get('value', _('unknown'))
+        message = self.extra.get('message', '')
+
+        try:
+            if int(value) > 0:
+                return _("%(user)s awarded an extra %(value)s reputation points to %(users)s: %(message)s") % {
+                'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
+                'value': value, 'users':self.affected_links(viewer), 'message': message
+                }
+            else:
+                return _("%(user)s penalised %(users)s in %(value)s reputation points: %(message)s") % {
+                'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
+                'value': value, 'users':self.affected_links(viewer), 'message': message
+                }
+        except Exception, e:
+            return ''
+
+class AwardAction(ActionProxy):
+    verb = _("was awarded")
+
+    def process_data(self, badge, trigger):
+        self.__dict__['_badge'] = badge
+        self.__dict__['_trigger'] = trigger
+
+    def process_action(self):
+        badge = self.__dict__['_badge']
+        trigger = self.__dict__['_trigger']
+
+        award = Award(user=self.user, badge=badge, trigger=trigger, action=self)
+        if self.node:
+            award.node = self.node
+
+        award.save()
+        award.badge.awarded_count = F('awarded_count') + 1
+        award.badge.save()
+
+        if award.badge.type == Badge.GOLD:
+            self.user.gold += 1
+        if award.badge.type == Badge.SILVER:
+            self.user.silver += 1
+        if award.badge.type == Badge.BRONZE:
+            self.user.bronze += 1
+
+        self.user.save()
+
+        self.user.message_set.create(message=_(
+                """Congratulations, you have received a badge '%(badge_name)s'. Check out <a href=\"%(profile_url)s\">your profile</a>."""
+                ) %
+        dict(badge_name=award.badge.name, profile_url=self.user.get_profile_url()))
+
+    def cancel_action(self):
+        award = self.award
+        badge = award.badge
+        badge.awarded_count = F('awarded_count') - 1
+        badge.save()
+        award.delete()
+
+    @classmethod
+    def get_for(cls, user, badge, node=False):
+        try:
+            if node is False:
+                return Award.objects.get(user=user, badge=badge).action
+            else:
+                return Award.objects.get(user=user, node=node, badge=badge).action
+        except:
+            return None
+
+    def describe(self, viewer=None):
+        return _("%(user)s %(were_was)s awarded the %(badge_name)s badge") % {
+        'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
+        'were_was': self.viewer_or_user_verb(viewer, self.user, _('were'), _('was')),
+        'badge_name': self.award.badge.name,
+        }
+
+class SuspendAction(ActionProxy):
+    verb = _("suspended")
+
+    def process_data(self, **kwargs):
+        self._suspended = kwargs.pop('suspended')
+        self.extra = kwargs
+
+    def repute_users(self):
+        self.repute(self._suspended, 0)
+
+    def process_action(self):
+        self._suspended.is_active = False
+        self._suspended.save()
+
+    def cancel_action(self):
+        for u in User.objects.filter(reputes__action=self).distinct():
+            u.is_active = True
+            u._pop_suspension_cache()
+            u.save()
+            u.message_set.create(message=_("Your suspension has been removed."))
+
+    def describe(self, viewer=None):
+        if self.extra.get('bantype', 'indefinitely') == 'forxdays' and self.extra.get('forxdays', None):
+            suspension = _("for %s days") % self.extra['forxdays']
+        else:
+            suspension = _("indefinetely")
+
+        return _("%(user)s suspended %(users)s %(suspension)s: %(msg)s") % {
+        'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
+        'users': self.affected_links(viewer), 'suspension': suspension, 'msg': self.extra.get('publicmsg', _('Bad behaviour'))
+        }
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/admin.py b/forum/modules/template_loader.py/forum/admin.py
new file mode 100644 (file)
index 0000000..c327ff8
--- /dev/null
@@ -0,0 +1,66 @@
+# -*- coding: utf-8 -*-
+
+#from django.contrib import admin
+#from models import *
+#
+#class AnonymousQuestionAdmin(admin.ModelAdmin):
+#    """AnonymousQuestion admin class"""
+#
+#class NodeAdmin(admin.ModelAdmin):
+#    """Question admin class"""
+#
+#class TagAdmin(admin.ModelAdmin):
+#    """Tag admin class"""
+#
+#class Answerdmin(admin.ModelAdmin):
+#    """Answer admin class"""
+#
+#class CommentAdmin(admin.ModelAdmin):
+#    """  admin class"""
+#
+#class VoteAdmin(admin.ModelAdmin):
+#    """  admin class"""
+#
+#class FlaggedItemAdmin(admin.ModelAdmin):
+#    """  admin class"""
+#
+#class FavoriteQuestionAdmin(admin.ModelAdmin):
+#    """  admin class"""
+#
+#class QuestionRevisionAdmin(admin.ModelAdmin):
+#    """  admin class"""
+#
+#class AnswerRevisionAdmin(admin.ModelAdmin):
+#    """  admin class"""
+#
+#class AwardAdmin(admin.ModelAdmin):
+#    """  admin class"""
+#
+#class BadgeAdmin(admin.ModelAdmin):
+#    """  admin class"""
+#
+#class ReputeAdmin(admin.ModelAdmin):
+#    """  admin class"""
+#
+#class ActionAdmin(admin.ModelAdmin):
+#    """  admin class"""
+    
+#class BookAdmin(admin.ModelAdmin):
+#    """  admin class"""
+    
+#class BookAuthorInfoAdmin(admin.ModelAdmin):
+#    """  admin class"""
+    
+#class BookAuthorRssAdmin(admin.ModelAdmin):
+#    """  admin class"""
+    
+#admin.site.register(Node, NodeAdmin)
+#admin.site.register(Tag, TagAdmin)
+#admin.site.register(QuestionRevision, QuestionRevisionAdmin)
+#admin.site.register(AnswerRevision, AnswerRevisionAdmin)
+#admin.site.register(Badge, BadgeAdmin)
+#admin.site.register(Award, AwardAdmin)
+#admin.site.register(Action, ActionAdmin)
+#admin.site.register(Book, BookAdmin)
+#admin.site.register(BookAuthorInfo, BookAuthorInfoAdmin)
+#admin.site.register(BookAuthorRss, BookAuthorRssAdmin)
diff --git a/forum/modules/template_loader.py/forum/authentication/__init__.py b/forum/modules/template_loader.py/forum/authentication/__init__.py
new file mode 100644 (file)
index 0000000..8dbf825
--- /dev/null
@@ -0,0 +1,33 @@
+import re
+import django.dispatch
+from forum.modules import get_modules_script_classes
+from forum.authentication.base import AuthenticationConsumer, ConsumerTemplateContext
+
+class ConsumerAndContext:
+    def __init__(self, id, consumer, context):
+        self.id = id
+        self._consumer = consumer
+
+        context.id = id
+        self.context = context
+
+    @property
+    def consumer(self):
+        return self._consumer()
+
+consumers = dict([
+            (re.sub('AuthConsumer$', '', name).lower(), cls) for name, cls
+            in get_modules_script_classes('authentication', AuthenticationConsumer).items()
+            if not re.search('AbstractAuthConsumer$', name)
+        ])
+
+contexts = dict([
+            (re.sub('AuthContext$', '', name).lower(), cls) for name, cls
+            in get_modules_script_classes('authentication', ConsumerTemplateContext).items()
+        ])
+
+AUTH_PROVIDERS = dict([
+            (name, ConsumerAndContext(name, consumers[name], contexts[name])) for name in consumers.keys()
+            if name in contexts
+        ])
+
diff --git a/forum/modules/template_loader.py/forum/authentication/base.py b/forum/modules/template_loader.py/forum/authentication/base.py
new file mode 100644 (file)
index 0000000..9900586
--- /dev/null
@@ -0,0 +1,44 @@
+
+class AuthenticationConsumer(object):
+
+    def prepare_authentication_request(self, request, redirect_to):
+        raise NotImplementedError()
+
+    def process_authentication_request(self, response):
+        raise NotImplementedError()
+
+    def get_user_data(self, key):
+        raise NotImplementedError()
+
+
+class ConsumerTemplateContext(object):
+    """
+        Class that provides information about a certain authentication provider context in the signin page.
+
+        class attributes:
+
+        mode - one of BIGICON, SMALLICON, FORM
+
+        human_name - the human readable name of the provider
+
+        extra_js - some providers require us to load extra javascript on the signin page for them to work,
+        this is the place to add those files in the form of a list
+
+        extra_css - same as extra_js but for css files
+    """
+    mode = ''
+    weight = 500
+    human_name = ''
+    extra_js = []
+    extra_css = []
+    show_to_logged_in_user = True
+
+    @classmethod
+    def readable_key(cls, key):
+        return key.key
+
+class InvalidAuthentication(Exception):
+    def __init__(self, message):
+        self.message = message
+        
+    
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/badges/__init__.py b/forum/modules/template_loader.py/forum/badges/__init__.py
new file mode 100644 (file)
index 0000000..c413e82
--- /dev/null
@@ -0,0 +1,6 @@
+from forum.modules import get_modules_script
+
+get_modules_script('badges')
+
+from base import BadgesMeta
+
diff --git a/forum/modules/template_loader.py/forum/badges/base.py b/forum/modules/template_loader.py/forum/badges/base.py
new file mode 100644 (file)
index 0000000..79fcb52
--- /dev/null
@@ -0,0 +1,77 @@
+import re
+from string import lower
+
+from django.core.exceptions import MultipleObjectsReturned
+from django.db.models.signals import post_save
+
+from forum.models import Badge, Node, Action
+from forum.actions import AwardAction
+
+import logging
+
+installed = dict([(b.cls, b) for b in Badge.objects.all()])
+
+class BadgesMeta(type):
+    by_class = {}
+    by_id = {}
+
+    def __new__(mcs, name, bases, dic):
+        badge = type.__new__(mcs, name, bases, dic)
+
+        if not dic.get('abstract', False):
+            if not name in installed:
+                badge.ondb = Badge(cls=name, type=dic.get('type', Badge.BRONZE))
+                badge.ondb.save()
+            else:
+                badge.ondb = installed[name]
+
+            inst = badge()
+
+            def hook(action, new):
+                user = inst.award_to(action)
+
+                if user:
+                    badge.award(user, action, badge.award_once)
+
+            for action in badge.listen_to:
+                action.hook(hook)
+
+            BadgesMeta.by_class[name] = badge
+            badge.ondb.__dict__['_class'] = inst
+            BadgesMeta.by_id[badge.ondb.id] = badge
+
+        return badge
+
+class AbstractBadge(object):
+    __metaclass__ = BadgesMeta
+
+    abstract = True
+    award_once = False
+
+    @property
+    def name(self):
+        raise NotImplementedError
+
+    @property
+    def description(self):
+        raise NotImplementedError
+
+    @classmethod
+    def award(cls, user, action, once=False):
+        try:
+            if once:
+                node = None
+                awarded = AwardAction.get_for(user, cls.ondb)
+            else:
+                node = action.node
+                awarded = AwardAction.get_for(user, cls.ondb, node)
+
+            trigger = isinstance(action, Action) and action or None
+
+            if not awarded:
+                AwardAction(user=user, node=node).save(data=dict(badge=cls.ondb, trigger=trigger))
+        except MultipleObjectsReturned:
+            if node:
+                logging.error('Found multiple %s badges awarded for user %s (%s)' % (self.name, user.username, user.id))
+            else:
+                logging.error('Found multiple %s badges awarded for user %s (%s) and node %s' % (self.name, user.username, user.id, node.id))
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/context.py b/forum/modules/template_loader.py/forum/context.py
new file mode 100644 (file)
index 0000000..641af38
--- /dev/null
@@ -0,0 +1,23 @@
+from forum import settings
+
+def application_settings(context):
+    return {'settings': settings}
+
+def auth_processor(request):
+    if hasattr(request, 'user'):
+        user = request.user
+        if user.is_authenticated():
+            messages = user.message_set.all()
+        else:
+            messages = None
+    else:
+        from django.contrib.auth.models import AnonymousUser
+        user = AnonymousUser()
+        messages = None
+
+    from django.core.context_processors import PermWrapper
+    return {
+        'user': user,
+        'messages': messages,
+        'perms': PermWrapper(user),
+    }
diff --git a/forum/modules/template_loader.py/forum/feed.py b/forum/modules/template_loader.py/forum/feed.py
new file mode 100644 (file)
index 0000000..02c309d
--- /dev/null
@@ -0,0 +1,108 @@
+try:
+    from django.contrib.syndication.views import Feed, FeedDoesNotExist, add_domain
+    old_version = False
+except:
+    from django.contrib.syndication.feeds import Feed, FeedDoesNotExist, add_domain
+    old_version = True
+
+from django.http import HttpResponse
+from django.utils.translation import ugettext as _
+from django.utils.safestring import mark_safe
+from models import Question
+from forum import settings
+from forum.modules import decorate
+from forum.utils.pagination import generate_uri
+
+@decorate(add_domain, needs_origin=False)
+def add_domain(domain, url, *args, **kwargs):
+    return "%s%s" % (settings.APP_BASE_URL, url)
+
+class BaseNodeFeed(Feed):
+    if old_version:
+        title_template = "feeds/rss_title.html"
+        description_template = "feeds/rss_description.html"
+
+    def __init__(self, request, title, description, url):
+        self._title = title
+        self._description = mark_safe(unicode(description))
+        self._url = url
+
+        if old_version:
+            super(BaseNodeFeed, self).__init__('', request)
+
+    def title(self):
+        return self._title
+
+    def link(self):
+        return self._url
+
+    def description(self):
+        return self._description
+
+    def item_title(self, item):
+        return item.title
+
+    def item_description(self, item):
+        return item.html
+
+    def item_link(self, item):
+        return item.leaf.get_absolute_url()
+
+    def item_author_name(self, item):
+        return item.author.username
+
+    def item_author_link(self, item):
+        return item.author.get_profile_url()
+
+    def item_pubdate(self, item):
+        return item.added_at
+
+    if old_version:
+        def __call__(self, request):
+            feedgen = self.get_feed('')
+            response = HttpResponse(mimetype=feedgen.mime_type)
+            feedgen.write(response, 'utf-8')
+            return response
+
+
+class RssQuestionFeed(BaseNodeFeed):
+    def __init__(self, request, question_list, title, description):
+        url = request.path + "&" + generate_uri(request.GET, (_('page'), _('pagesize'), _('sort')))
+        super(RssQuestionFeed, self).__init__(request, title, description, url)
+
+        self._question_list = question_list
+
+    def item_categories(self, item):
+        return item.tagname_list()  
+
+    def items(self):
+       return self._question_list[:30]
+
+class RssAnswerFeed(BaseNodeFeed):
+    if old_version:
+        title_template = "feeds/rss_answer_title.html"
+
+    def __init__(self, request, question, include_comments=False):
+        super(RssAnswerFeed, self).__init__(request, _("Answers to: %s") % question.title, question.html, question.get_absolute_url())
+        self._question = question
+        self._include_comments = include_comments
+
+    def items(self):
+        if self._include_comments:
+            qs = self._question.all_children
+        else:
+            qs = self._question.answers
+
+        return qs.filter_state(deleted=False).order_by('-added_at')[:30]
+
+    def item_title(self, item):
+        if item.node_type == "answer":
+            return _("Answer by %s") % item.author.username
+        else:
+            return _("Comment by %(cauthor)s on %(pauthor)s's %(qora)s") % dict(
+                cauthor=item.author.username, pauthor=item.parent.author.username, qora=(item.parent.node_type == "answer" and _("answer") or _("question"))
+            )
+
+
+
+
diff --git a/forum/modules/template_loader.py/forum/forms/__init__.py b/forum/modules/template_loader.py/forum/forms/__init__.py
new file mode 100644 (file)
index 0000000..ea5108c
--- /dev/null
@@ -0,0 +1,4 @@
+from qanda import *
+from admin import *
+from auth import *
+from general import *
diff --git a/forum/modules/template_loader.py/forum/forms/admin.py b/forum/modules/template_loader.py/forum/forms/admin.py
new file mode 100644 (file)
index 0000000..1ff2e85
--- /dev/null
@@ -0,0 +1,107 @@
+import socket
+from django import forms
+from django.utils.translation import ugettext as _
+from django.contrib.admin.widgets import FilteredSelectMultiple, AdminDateWidget
+from qanda import TitleField, EditorField
+from forum import settings
+from forum.models.node import NodeMetaClass
+from forum.models import User
+
+class IPListField(forms.CharField):
+    def clean(self, value):
+        ips = [ip.strip() for ip in value.strip().strip(',').split(',')]
+        iplist = []
+
+        if len(ips) < 1:
+            raise forms.ValidationError(_('Please input at least one ip address'))
+
+        for ip in ips:
+            try:
+                socket.inet_aton(ip)
+            except socket.error:
+                raise forms.ValidationError(_('Invalid ip address: %s' % ip))
+
+            if not len(ip.split('.')) == 4:
+                raise forms.ValidationError(_('Please use the dotted quad notation for the ip addresses'))
+
+            iplist.append(ip)
+
+        return iplist
+
+class MaintenanceModeForm(forms.Form):
+    ips = IPListField(label=_('Allow ips'),
+                      help_text=_('Comma separated list of ips allowed to access the site while in maintenance'),
+                      required=True,
+                      widget=forms.TextInput(attrs={'class': 'longstring'}))
+
+    message = forms.CharField(label=_('Message'),
+                              help_text=_('A message to display to your site visitors while in maintainance mode'),
+                              widget=forms.Textarea)
+
+
+TEMPLATE_CHOICES = (
+('default', _('Default')),
+('sidebar', _('Default with sidebar')),
+('none', _('None')),
+)
+
+RENDER_CHOICES = (
+('markdown', _('Markdown')),
+('html', _('HTML')),
+('escape', _('Escaped'))
+)
+
+class UrlFieldWidget(forms.TextInput):
+    def render(self, name, value, attrs=None):
+        if not value:
+            value = ''
+
+        return """
+                <input class="url_field" type="text" name="%(name)s" value="%(value)s" />
+                <a class="url_field_anchor" target="_blank" href="%(app_url)s"></a>
+            """  % {'name': name, 'value': value, 'app_url': settings.APP_URL}
+
+
+class PageForm(forms.Form):
+    def __init__(self, page, *args, **kwargs):
+        if page:
+            initial = page.extra
+            initial.update(dict(title=page.title, content=page.body))
+            super(PageForm, self).__init__(initial=initial, *args, **kwargs)
+        else:
+            super(PageForm, self).__init__(*args, **kwargs)
+
+
+    title  = forms.CharField(label=_('Title'), max_length=255, widget=forms.TextInput(attrs={'class': 'longstring'}),
+                             initial='New page')
+    path  = forms.CharField(label=_('Page URL'), widget=UrlFieldWidget, initial='pages/new/')
+
+    content = forms.CharField(label=_('Page Content'), widget=forms.Textarea(attrs={'rows': 30}))
+    mimetype = forms.CharField(label=_('Mime Type'), initial='text/html')
+
+    render = forms.ChoiceField(widget=forms.RadioSelect, choices=RENDER_CHOICES, initial='markdown',
+                               label=_('Render Mode'))
+
+    template = forms.ChoiceField(widget=forms.RadioSelect, choices=TEMPLATE_CHOICES, initial='default',
+                                 label=_('Template'))
+    sidebar = forms.CharField(label=_('Sidebar Content'), widget=forms.Textarea(attrs={'rows': 20}), required=False)
+    sidebar_wrap = forms.BooleanField(label=_("Wrap sidebar block"), initial=True, required=False)
+    sidebar_render = forms.ChoiceField(widget=forms.RadioSelect, choices=RENDER_CHOICES, initial='markdown',
+                                       label=_('Sidebar Render Mode'))
+
+    comments = forms.BooleanField(label=_("Allow comments"), initial=False, required=False)
+
+from forum.forms.auth import SimpleRegistrationForm
+from forum.forms.general import SetPasswordForm
+
+
+class CreateUserForm(SimpleRegistrationForm, SetPasswordForm):
+    validate_email = forms.BooleanField(required=False, label=_('send validation email'))
+
+    def __init__(self, *args, **kwargs):
+        super(CreateUserForm, self).__init__(*args, **kwargs)
+        self.fields.keyOrder = ['username', 'email', 'validate_email', 'password1', 'password2']
+        self.fields['email'].label = _('email address')
+
+
+    
diff --git a/forum/modules/template_loader.py/forum/forms/auth.py b/forum/modules/template_loader.py/forum/forms/auth.py
new file mode 100644 (file)
index 0000000..c1a7c09
--- /dev/null
@@ -0,0 +1,65 @@
+from general import NextUrlField,  UserNameField,  UserEmailField, SetPasswordForm
+from forum.models import Question, User
+from forum.settings import INITIAL_EMAIL_SUBSCRIBE_OPTION
+from django.contrib.contenttypes.models import ContentType
+from django.utils.translation import ugettext as _
+from django.utils.safestring import mark_safe
+from django import forms
+import logging
+
+class SimpleRegistrationForm(forms.Form):
+    next = NextUrlField()
+    username = UserNameField()
+    email = UserEmailField()
+
+class TemporaryLoginRequestForm(forms.Form):
+    def __init__(self, data=None):
+        super(TemporaryLoginRequestForm, self).__init__(data)
+        self.user_cache = None
+
+    email = forms.EmailField(
+            required=True,
+            label=_("Your account email"),
+            error_messages={
+                'required': _("You cannot leave this field blank"),
+                'invalid': _('please enter a valid email address'),
+            }
+    )
+
+    def clean_email(self):
+        users = list(User.objects.filter(email=self.cleaned_data['email']))
+
+        if not len(users):
+            raise forms.ValidationError(_("Sorry, but this email is not on our database."))
+
+        self.user_cache = users
+        return self.cleaned_data['email']
+
+
+class SimpleEmailSubscribeForm(forms.Form):
+    SIMPLE_SUBSCRIBE_CHOICES = (
+        ('y',_('okay, let\'s try!')),
+        ('n',_('no OSQA community email please, thanks'))
+    )
+    subscribe = forms.ChoiceField(widget=forms.widgets.RadioSelect(), \
+                                error_messages={'required':_('please choose one of the options above')},
+                                choices=SIMPLE_SUBSCRIBE_CHOICES, initial=INITIAL_EMAIL_SUBSCRIBE_OPTION)
+
+
+class ChangePasswordForm(SetPasswordForm):
+    """ change password form """
+    oldpw = forms.CharField(widget=forms.PasswordInput(attrs={'class':'required'}),
+                label=mark_safe(_('Current password')))
+
+    def __init__(self, data=None, user=None, *args, **kwargs):
+        if user is None:
+            raise TypeError("Keyword argument 'user' must be supplied")
+        super(ChangePasswordForm, self).__init__(data, *args, **kwargs)
+        self.user = user
+
+    def clean_oldpw(self):
+        """ test old password """
+        if not self.user.check_password(self.cleaned_data['oldpw']):
+            raise forms.ValidationError(_("Old password is incorrect. \
+                    Please enter the correct password."))
+        return self.cleaned_data['oldpw']
diff --git a/forum/modules/template_loader.py/forum/forms/general.py b/forum/modules/template_loader.py/forum/forms/general.py
new file mode 100644 (file)
index 0000000..e0348a8
--- /dev/null
@@ -0,0 +1,173 @@
+from django import forms
+import re
+from django.utils.translation import ugettext as _
+from django.utils.safestring import mark_safe
+from forum import settings
+from django.http import str_to_unicode
+from forum.models import User
+from forum.modules import call_all_handlers
+import urllib
+import logging
+
+DEFAULT_NEXT = getattr(settings, 'APP_BASE_URL')
+def clean_next(next):
+    if next is None:
+        return DEFAULT_NEXT
+    next = str_to_unicode(urllib.unquote(next), 'utf-8')
+    next = next.strip()
+    if next.startswith('/'):
+        return next
+    return DEFAULT_NEXT
+
+def get_next_url(request):
+    return clean_next(request.REQUEST.get('next'))
+
+class StrippedNonEmptyCharField(forms.CharField):
+    def clean(self,value):
+        value = value.strip()
+        if self.required and value == '':
+            raise forms.ValidationError(_('this field is required'))
+        return value
+
+class NextUrlField(forms.CharField):
+    def __init__(self):
+        super(NextUrlField,self).__init__(max_length = 255,widget = forms.HiddenInput(),required = False)
+    def clean(self,value):
+        return clean_next(value)
+
+login_form_widget_attrs = { 'class': 'required login' }
+username_re = re.compile(r'^[\w\s ]+$', re.UNICODE)
+
+class UserNameField(StrippedNonEmptyCharField):
+    def __init__(self,db_model=User, db_field='username', must_exist=False,skip_clean=False,label=_('choose a username'),**kw):
+        self.must_exist = must_exist
+        self.skip_clean = skip_clean
+        self.db_model = db_model 
+        self.db_field = db_field
+        error_messages={'required':_('user name is required'),
+                        'taken':_('sorry, this name is taken, please choose another'),
+                        'forbidden':_('sorry, this name is not allowed, please choose another'),
+                        'missing':_('sorry, there is no user with this name'),
+                        'multiple-taken':_('sorry, we have a serious error - user name is taken by several users'),
+                        'invalid':_('user name can only consist of letters, empty space and underscore'),
+                        'toshort':_('user name is to short, please use at least %d characters') % settings.MIN_USERNAME_LENGTH
+                    }
+        if 'error_messages' in kw:
+            error_messages.update(kw['error_messages'])
+            del kw['error_messages']
+        super(UserNameField,self).__init__(max_length=30,
+                widget=forms.TextInput(attrs=login_form_widget_attrs),
+                label=label,
+                error_messages=error_messages,
+                **kw
+                )
+
+    def clean(self,username):
+        """ validate username """
+        if self.skip_clean == True:
+            return username
+        if hasattr(self, 'user_instance') and isinstance(self.user_instance, User):
+            if username == self.user_instance.username:
+                return username
+        try:
+            username = super(UserNameField, self).clean(username)
+        except forms.ValidationError:
+            raise forms.ValidationError(self.error_messages['required'])
+        if len(username) < settings.MIN_USERNAME_LENGTH:
+            raise forms.ValidationError(self.error_messages['toshort'])
+        if self.required and not username_re.match(username):
+            raise forms.ValidationError(self.error_messages['invalid'])
+        if username in settings.RESERVED_USERNAMES:
+            raise forms.ValidationError(self.error_messages['forbidden'])
+        try:
+            user = self.db_model.objects.get(
+                    **{'%s' % self.db_field : username}
+            )
+            if user:
+                if self.must_exist:
+                    return username
+                else:
+                    raise forms.ValidationError(self.error_messages['taken'])
+        except self.db_model.DoesNotExist:
+            if self.must_exist:
+                raise forms.ValidationError(self.error_messages['missing'])
+            else:
+                return username
+        except self.db_model.MultipleObjectsReturned:
+            raise forms.ValidationError(self.error_messages['multiple-taken'])
+
+class UserEmailField(forms.EmailField):
+    def __init__(self,skip_clean=False,**kw):
+        self.skip_clean = skip_clean
+        super(UserEmailField,self).__init__(widget=forms.TextInput(attrs=dict(login_form_widget_attrs,
+            maxlength=200)), label=mark_safe(_('your email address')),
+            error_messages={'required':_('email address is required'),
+                            'invalid':_('please enter a valid email address'),
+                            'taken':_('this email is already used by someone else, please choose another'),
+                            },
+            **kw
+            )
+
+    def clean(self,email):
+        """ validate if email exist in database
+        from legacy register
+        return: raise error if it exist """
+        email = super(UserEmailField,self).clean(email.strip())
+        if self.skip_clean:
+            return email
+        if settings.EMAIL_UNIQUE == True:
+            try:
+                user = User.objects.get(email = email)
+                raise forms.ValidationError(self.error_messages['taken'])
+            except User.DoesNotExist:
+                return email
+            except User.MultipleObjectsReturned:
+                raise forms.ValidationError(self.error_messages['taken'])
+        else:
+            return email 
+
+class SetPasswordForm(forms.Form):
+    password1 = forms.CharField(widget=forms.PasswordInput(attrs=login_form_widget_attrs),
+                                label=_('choose password'),
+                                error_messages={'required':_('password is required')},
+                                )
+    password2 = forms.CharField(widget=forms.PasswordInput(attrs=login_form_widget_attrs),
+                                label=mark_safe(_('retype password')),
+                                error_messages={'required':_('please, retype your password'),
+                                                'nomatch':_('sorry, entered passwords did not match, please try again')},
+                                )
+
+    def __init__(self, data=None, user=None, *args, **kwargs):
+        super(SetPasswordForm, self).__init__(data, *args, **kwargs)
+
+    def clean_password2(self):
+        """
+        Validates that the two password inputs match.
+        
+        """
+        if 'password1' in self.cleaned_data:
+            if self.cleaned_data['password1'] == self.cleaned_data['password2']:
+                self.password = self.cleaned_data['password2']
+                self.cleaned_data['password'] = self.cleaned_data['password2']
+                return self.cleaned_data['password2']
+            else:
+                del self.cleaned_data['password2']
+                raise forms.ValidationError(self.fields['password2'].error_messages['nomatch'])
+        else:
+            return self.cleaned_data['password2']
+
+class SimpleCaptchaForm(forms.Form):
+    fields = {}
+
+    def __init__(self, *args, **kwargs):
+        super(SimpleCaptchaForm, self).__init__(*args, **kwargs)
+
+        spam_fields = call_all_handlers('create_anti_spam_field')
+        if spam_fields:
+            spam_fields = dict(spam_fields)
+            for name, field in spam_fields.items():
+                self.fields[name] = field
+
+            self._anti_spam_fields = spam_fields.keys()
+        else:
+            self._anti_spam_fields = []
diff --git a/forum/modules/template_loader.py/forum/forms/qanda.py b/forum/modules/template_loader.py/forum/forms/qanda.py
new file mode 100644 (file)
index 0000000..9890640
--- /dev/null
@@ -0,0 +1,341 @@
+import re
+from datetime import date
+from django import forms
+from forum.models import *
+from django.utils.translation import ugettext as _
+from django.contrib.humanize.templatetags.humanize import apnumber
+
+from django.utils.safestring import mark_safe
+from general import NextUrlField, UserNameField, SetPasswordForm
+from forum import settings
+
+from forum.modules import call_all_handlers
+
+import logging
+
+class TitleField(forms.CharField):
+    def __init__(self, *args, **kwargs):
+        super(TitleField, self).__init__(*args, **kwargs)
+        self.required = True
+        self.widget = forms.TextInput(attrs={'size' : 70, 'autocomplete' : 'off'})
+        self.max_length = 255
+        self.label  = _('title')
+        self.help_text = _('please enter a descriptive title for your question')
+        self.initial = ''
+
+    def clean(self, value):
+        if len(value) < settings.FORM_MIN_QUESTION_TITLE:
+            raise forms.ValidationError(_('title must be must be at least %s characters') % settings.FORM_MIN_QUESTION_TITLE)
+
+        return value
+
+class EditorField(forms.CharField):
+    def __init__(self, *args, **kwargs):
+        super(EditorField, self).__init__(*args, **kwargs)
+        self.widget = forms.Textarea(attrs={'id':'editor'})
+        self.label  = _('content')
+        self.help_text = u''
+        self.initial = ''
+
+
+class QuestionEditorField(EditorField):
+    def __init__(self, *args, **kwargs):
+        super(QuestionEditorField, self).__init__(*args, **kwargs)
+        self.required = not bool(settings.FORM_EMPTY_QUESTION_BODY)
+
+
+    def clean(self, value):
+        if not bool(settings.FORM_EMPTY_QUESTION_BODY) and (len(re.sub('[ ]{2,}', ' ', value)) < settings.FORM_MIN_QUESTION_BODY):
+            raise forms.ValidationError(_('question content must be at least %s characters') % settings.FORM_MIN_QUESTION_BODY)
+
+        return value
+
+class AnswerEditorField(EditorField):
+    def __init__(self, *args, **kwargs):
+        super(AnswerEditorField, self).__init__(*args, **kwargs)
+        self.required = True
+
+    def clean(self, value):
+        if len(re.sub('[ ]{2,}', ' ', value)) < settings.FORM_MIN_QUESTION_BODY:
+            raise forms.ValidationError(_('answer content must be at least %s characters') % settings.FORM_MIN_QUESTION_BODY)
+
+        return value
+
+
+class TagNamesField(forms.CharField):
+    def __init__(self, user=None, *args, **kwargs):
+        super(TagNamesField, self).__init__(*args, **kwargs)
+        self.required = True
+        self.widget = forms.TextInput(attrs={'size' : 50, 'autocomplete' : 'off'})
+        self.max_length = 255
+        self.label  = _('tags')
+        #self.help_text = _('please use space to separate tags (this enables autocomplete feature)')
+        self.help_text = _('Tags are short keywords, with no spaces within. At least %(min)s and up to %(max)s tags can be used.') % {
+            'min': settings.FORM_MIN_NUMBER_OF_TAGS, 'max': settings.FORM_MAX_NUMBER_OF_TAGS    
+        }
+        self.initial = ''
+        self.user = user
+
+    def clean(self, value):
+        value = super(TagNamesField, self).clean(value)
+        data = value.strip().lower()
+
+        split_re = re.compile(r'[ ,]+')
+        list = {}
+        for tag in split_re.split(data):
+            list[tag] = tag
+
+        if len(list) > settings.FORM_MAX_NUMBER_OF_TAGS or len(list) < settings.FORM_MIN_NUMBER_OF_TAGS:
+            raise forms.ValidationError(_('please use between %(min)s and %(max)s tags') % { 'min': settings.FORM_MIN_NUMBER_OF_TAGS, 'max': settings.FORM_MAX_NUMBER_OF_TAGS})
+
+        list_temp = []
+        tagname_re = re.compile(r'^[\w+\.-]+$', re.UNICODE)
+        for key,tag in list.items():
+            if len(tag) > settings.FORM_MAX_LENGTH_OF_TAG or len(tag) < settings.FORM_MIN_LENGTH_OF_TAG:
+                raise forms.ValidationError(_('please use between %(min)s and %(max)s characters in you tags') % { 'min': settings.FORM_MIN_LENGTH_OF_TAG, 'max': settings.FORM_MAX_LENGTH_OF_TAG})
+            if not tagname_re.match(tag):
+                raise forms.ValidationError(_('please use following characters in tags: letters , numbers, and characters \'.-_\''))
+            # only keep one same tag
+            if tag not in list_temp and len(tag.strip()) > 0:
+                list_temp.append(tag)
+
+        if settings.LIMIT_TAG_CREATION and not self.user.can_create_tags():
+            existent = Tag.objects.filter(name__in=list_temp).values_list('name', flat=True)
+
+            if len(existent) < len(list_temp):
+                unexistent = [n for n in list_temp if not n in existent]
+                raise forms.ValidationError(_("You don't have enough reputation to create new tags. The following tags do not exist yet: %s") %
+                        ', '.join(unexistent))
+
+
+        return u' '.join(list_temp)
+
+class WikiField(forms.BooleanField):
+    def __init__(self, disabled=False, *args, **kwargs):
+        super(WikiField, self).__init__(*args, **kwargs)
+        self.required = False
+        self.label  = _('community wiki')
+        self.help_text = _('if you choose community wiki option, the question and answer do not generate points and name of author will not be shown')
+        if disabled:
+            self.widget=forms.CheckboxInput(attrs={'disabled': "disabled"})
+    def clean(self,value):
+        return value
+
+class EmailNotifyField(forms.BooleanField):
+    def __init__(self, *args, **kwargs):
+        super(EmailNotifyField, self).__init__(*args, **kwargs)
+        self.required = False
+        self.widget.attrs['class'] = 'nomargin'
+
+class SummaryField(forms.CharField):
+    def __init__(self, *args, **kwargs):
+        super(SummaryField, self).__init__(*args, **kwargs)
+        self.required = False
+        self.widget = forms.TextInput(attrs={'size' : 50, 'autocomplete' : 'off'})
+        self.max_length = 300
+        self.label  = _('update summary:')
+        self.help_text = _('enter a brief summary of your revision (e.g. fixed spelling, grammar, improved style, this field is optional)')
+
+
+class FeedbackForm(forms.Form):
+    message = forms.CharField(label=_('Your message:'), max_length=800,widget=forms.Textarea(attrs={'cols':60}))
+    next = NextUrlField()
+
+    def __init__(self, user, *args, **kwargs):
+        super(FeedbackForm, self).__init__(*args, **kwargs)
+        if not user.is_authenticated():
+            self.fields['name'] = forms.CharField(label=_('Your name:'), required=False)
+            self.fields['email'] = forms.EmailField(label=_('Email (not shared with anyone):'), required=True)
+
+
+
+class AskForm(forms.Form):
+    title  = TitleField()
+    text   = QuestionEditorField()
+
+    def __init__(self, data=None, user=None, *args, **kwargs):
+        super(AskForm, self).__init__(data, *args, **kwargs)
+
+        self.fields['tags']   = TagNamesField(user)
+        
+        if int(user.reputation) < settings.CAPTCHA_IF_REP_LESS_THAN and not (user.is_superuser or user.is_staff):
+            spam_fields = call_all_handlers('create_anti_spam_field')
+            if spam_fields:
+                spam_fields = dict(spam_fields)
+                for name, field in spam_fields.items():
+                    self.fields[name] = field
+
+                self._anti_spam_fields = spam_fields.keys()
+            else:
+                self._anti_spam_fields = []
+
+        if settings.WIKI_ON:
+            self.fields['wiki'] = WikiField()
+
+class AnswerForm(forms.Form):
+    text   = AnswerEditorField()
+    wiki   = WikiField()
+
+    def __init__(self, data=None, user=None, *args, **kwargs):
+        super(AnswerForm, self).__init__(data, *args, **kwargs)
+        
+        if int(user.reputation) < settings.CAPTCHA_IF_REP_LESS_THAN and not (user.is_superuser or user.is_staff):
+            spam_fields = call_all_handlers('create_anti_spam_field')
+            if spam_fields:
+                spam_fields = dict(spam_fields)
+                for name, field in spam_fields.items():
+                    self.fields[name] = field
+
+                self._anti_spam_fields = spam_fields.keys()
+            else:
+                self._anti_spam_fields = []
+
+        if settings.WIKI_ON:
+            self.fields['wiki'] = WikiField()
+
+class RetagQuestionForm(forms.Form):
+    tags   = TagNamesField()
+    # initialize the default values
+    def __init__(self, question, *args, **kwargs):
+        super(RetagQuestionForm, self).__init__(*args, **kwargs)
+        self.fields['tags'].initial = question.tagnames
+
+class RevisionForm(forms.Form):
+    """
+    Lists revisions of a Question or Answer
+    """
+    revision = forms.ChoiceField(widget=forms.Select(attrs={'style' : 'width:520px'}))
+
+    def __init__(self, post, *args, **kwargs):
+        super(RevisionForm, self).__init__(*args, **kwargs)
+
+        revisions = post.revisions.all().values_list('revision', 'author__username', 'revised_at', 'summary').order_by('-revised_at')
+
+        date_format = '%c'
+        self.fields['revision'].choices = [
+            (r[0], u'%s - %s (%s) %s' % (r[0], r[1], r[2].strftime(date_format), r[3]))
+            for r in revisions]
+
+        self.fields['revision'].initial = post.active_revision.revision
+
+class EditQuestionForm(forms.Form):
+    title  = TitleField()
+    text   = QuestionEditorField()
+    summary = SummaryField()
+
+    def __init__(self, question, user, revision=None, *args, **kwargs):
+        super(EditQuestionForm, self).__init__(*args, **kwargs)
+
+        if revision is None:
+            revision = question.active_revision
+
+        self.fields['title'].initial = revision.title
+        self.fields['text'].initial = revision.body
+
+        self.fields['tags'] = TagNamesField(user)
+        self.fields['tags'].initial = revision.tagnames
+
+        if int(user.reputation) < settings.CAPTCHA_IF_REP_LESS_THAN and not (user.is_superuser or user.is_staff):
+            spam_fields = call_all_handlers('create_anti_spam_field')
+            if spam_fields:
+                spam_fields = dict(spam_fields)
+                for name, field in spam_fields.items():
+                    self.fields[name] = field
+
+                self._anti_spam_fields = spam_fields.keys()
+            else:
+                self._anti_spam_fields = []
+
+        if settings.WIKI_ON:
+            self.fields['wiki'] = WikiField(disabled=(question.nis.wiki and not user.can_cancel_wiki(question)), initial=question.nis.wiki)
+
+class EditAnswerForm(forms.Form):
+    text = AnswerEditorField()
+    summary = SummaryField()
+
+    def __init__(self, answer, user, revision=None, *args, **kwargs):
+        super(EditAnswerForm, self).__init__(*args, **kwargs)
+
+        if revision is None:
+            revision = answer.active_revision
+
+        self.fields['text'].initial = revision.body
+
+        if int(user.reputation) < settings.CAPTCHA_IF_REP_LESS_THAN and not (user.is_superuser or user.is_staff):
+            spam_fields = call_all_handlers('create_anti_spam_field')
+            if spam_fields:
+                spam_fields = dict(spam_fields)
+                for name, field in spam_fields.items():
+                    self.fields[name] = field
+
+                self._anti_spam_fields = spam_fields.keys()
+            else:
+                self._anti_spam_fields = []
+        
+        if settings.WIKI_ON:
+            self.fields['wiki'] = WikiField(disabled=(answer.nis.wiki and not user.can_cancel_wiki(answer)), initial=answer.nis.wiki)
+
+class EditUserForm(forms.Form):
+    email = forms.EmailField(label=u'Email', help_text=_('this email does not have to be linked to gravatar'), required=True, max_length=75, widget=forms.TextInput(attrs={'size' : 35}))
+    realname = forms.CharField(label=_('Real name'), required=False, max_length=255, widget=forms.TextInput(attrs={'size' : 35}))
+    website = forms.URLField(label=_('Website'), required=False, max_length=255, widget=forms.TextInput(attrs={'size' : 35}))
+    city = forms.CharField(label=_('Location'), required=False, max_length=255, widget=forms.TextInput(attrs={'size' : 35}))
+    birthday = forms.DateField(label=_('Date of birth'), help_text=_('will not be shown, used to calculate age, format: YYYY-MM-DD'), required=False, widget=forms.TextInput(attrs={'size' : 35}))
+    about = forms.CharField(label=_('Profile'), required=False, widget=forms.Textarea(attrs={'cols' : 60}))
+
+    def __init__(self, user, *args, **kwargs):
+        super(EditUserForm, self).__init__(*args, **kwargs)
+        if settings.EDITABLE_SCREEN_NAME:
+            self.fields['username'] = UserNameField(label=_('Screen name'))
+            self.fields['username'].initial = user.username
+            self.fields['username'].user_instance = user
+        self.fields['email'].initial = user.email
+        self.fields['realname'].initial = user.real_name
+        self.fields['website'].initial = user.website
+        self.fields['city'].initial = user.location
+
+        if user.date_of_birth is not None:
+            self.fields['birthday'].initial = user.date_of_birth
+        else:
+            self.fields['birthday'].initial = '1990-01-01'
+        self.fields['about'].initial = user.about
+        self.user = user
+
+    def clean_email(self):
+        if self.user.email != self.cleaned_data['email']:
+            if settings.EMAIL_UNIQUE == True:
+                if 'email' in self.cleaned_data:
+                    from forum.models import User
+                    try:
+                        User.objects.get(email = self.cleaned_data['email'])
+                    except User.DoesNotExist:
+                        return self.cleaned_data['email']
+                    except User.MultipleObjectsReturned:
+                        logging.error("Found multiple users sharing the same email: %s" % self.cleaned_data['email'])
+                        
+                    raise forms.ValidationError(_('this email has already been registered, please use another one'))
+        return self.cleaned_data['email']
+        
+
+NOTIFICATION_CHOICES = (
+    ('i', _('Instantly')),
+    #('d', _('Daily')),
+    #('w', _('Weekly')),
+    ('n', _('No notifications')),
+)
+
+class SubscriptionSettingsForm(forms.ModelForm):
+    enable_notifications = forms.BooleanField(widget=forms.HiddenInput, required=False)
+    member_joins = forms.ChoiceField(widget=forms.RadioSelect, choices=NOTIFICATION_CHOICES)
+    new_question = forms.ChoiceField(widget=forms.RadioSelect, choices=NOTIFICATION_CHOICES)
+    new_question_watched_tags = forms.ChoiceField(widget=forms.RadioSelect, choices=NOTIFICATION_CHOICES)
+    subscribed_questions = forms.ChoiceField(widget=forms.RadioSelect, choices=NOTIFICATION_CHOICES)
+
+    class Meta:
+        model = SubscriptionSettings
+
+class UserPreferencesForm(forms.Form):
+    sticky_sorts = forms.BooleanField(required=False, initial=False)
+
+
+
diff --git a/forum/modules/template_loader.py/forum/http_responses.py b/forum/modules/template_loader.py/forum/http_responses.py
new file mode 100644 (file)
index 0000000..7fae3b6
--- /dev/null
@@ -0,0 +1,27 @@
+from django.http import HttpResponse
+from django.template.loader import render_to_string
+from django.template import RequestContext
+
+from forum import settings
+
+class HttpResponseServiceUnavailable(HttpResponse):
+    def __init__(self, message):
+        super(HttpResponseServiceUnavailable, self).__init__(
+            content=render_to_string('503.html', {
+                'message': message,
+                'app_logo': settings.APP_LOGO,
+                'app_title': settings.APP_TITLE
+            }), status=503)
+
+class HttpResponseUnauthorized(HttpResponse):
+    def __init__(self, request):
+        if request.user.is_authenticated():
+            super(HttpResponseUnauthorized, self).__init__(
+                content=render_to_string('403.html', context_instance=RequestContext(request)),
+                status=403
+            )
+        else:
+            super(HttpResponseUnauthorized, self).__init__(
+                content=render_to_string('401.html', context_instance=RequestContext(request)),
+                status=401
+            )
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/management/__init__.py b/forum/modules/template_loader.py/forum/management/__init__.py
new file mode 100644 (file)
index 0000000..629678e
--- /dev/null
@@ -0,0 +1,42 @@
+from forum.modules import get_modules_script
+
+get_modules_script('management')
+
+from django.db.models.signals import post_syncdb
+import forum.models
+
+def post_syncdb_callback(sender, **kwargs):
+    # Import the needed libraries to use the database and detect the
+    # DB engine/sever type being currently employed.
+    from django.db import connection, connections
+
+    verbosity = int(kwargs["verbosity"])
+
+    # Get the DB engine being used for persistence for this app.
+    current_db_engine = connections.databases[connection.alias]['ENGINE']
+
+    # Make sure the updates are only executed for a MySQL DB.
+    if current_db_engine.find("mysql") > 0:
+        # Ok, mysql was found in the engine description.  Go ahead
+        # and attempt to execute the alter table statements.
+        cursor = connection.cursor()
+
+        # Pair the table names with the columns that need to be updated.
+        updatable_table_columns = {
+            "forum_tag": "name",
+            "auth_user": "username"
+        }
+
+        # Update each column in turn.
+        for table_name, column_name in updatable_table_columns.iteritems():
+            alter_table_statement = "ALTER TABLE %(table_name)s MODIFY %(column_name)s varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL;" % {
+                "table_name": table_name, "column_name": column_name}
+            log_status(verbosity,"Updating MySQL column with this statement: " + alter_table_statement)
+            cursor.execute(alter_table_statement)
+
+def log_status(verbosity, message):
+    if verbosity == 2:
+        print "[DEBUG] " + str(message)
+
+# Link the callback to the post_syncdb signal.
+post_syncdb.connect(post_syncdb_callback, sender=forum.models)
diff --git a/forum/modules/template_loader.py/forum/management/commands/__init__.py b/forum/modules/template_loader.py/forum/management/commands/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/forum/modules/template_loader.py/forum/management/commands/base_command.py b/forum/modules/template_loader.py/forum/management/commands/base_command.py
new file mode 100644 (file)
index 0000000..4a8a4b6
--- /dev/null
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+#encoding:utf-8
+#-------------------------------------------------------------------------------
+# Name:        Award badges command
+# Purpose:     This is a command file croning in background process regularly to
+#              query database and award badges for user's special acitivities.
+#
+# Author:      Mike, Sailing
+#
+# Created:     22/01/2009
+# Copyright:   (c) Mike 2009
+# Licence:     GPL V2
+#-------------------------------------------------------------------------------
+
+from datetime import datetime, date
+from django.core.management.base import NoArgsCommand
+from django.db import connection
+from django.shortcuts import get_object_or_404
+from django.contrib.contenttypes.models import ContentType
+
+from forum.models import *
+
+class BaseCommand(NoArgsCommand):
+    def update_activities_auditted(self, cursor, activity_ids):
+        # update processed rows to auditted
+        if len(activity_ids):
+            query = "UPDATE activity SET is_auditted = 1 WHERE id in (%s)"\
+                    % ','.join('%s' % item for item in activity_ids)
+            cursor.execute(query)
+    
+        
+        
+        
diff --git a/forum/modules/template_loader.py/forum/management/commands/checkinstall.py b/forum/modules/template_loader.py/forum/management/commands/checkinstall.py
new file mode 100644 (file)
index 0000000..6e37d11
--- /dev/null
@@ -0,0 +1,85 @@
+import re
+import sys, traceback
+from django.core.management.base import NoArgsCommand
+
+OK_MESSAGE = "  Found %(what)s version %(version)s - OK"
+
+OLD_VERSION_ERROR = """  ERROR: Found %(what)s version %(version)s - you should upgrade it to at least %(minimum)s.
+                Package installers like apt-get or yum usually maintain old versions of libraries in the repositories."""
+
+NOT_FOUND_ERROR = "ERROR: %(what)s was not found on your system."
+
+HOW_TO_INSTALL = """  Try easy_install %(what)s or download it from %(where)s"""
+
+IMPORT_ERROR_MESSAGE = """Importing %(what)s is throwing an exception. Here's the full stack trace:"""
+
+class Command(NoArgsCommand):
+    def handle_noargs(self, **options):
+        print "Checking dependencies:"
+
+        try:
+            import html5lib
+            print "  Found html5lib - OK"
+        except ImportError:
+            print NOT_FOUND_ERROR % dict(what='html5lib')
+            print HOW_TO_INSTALL % dict(what='html5lib', where='http://code.google.com/p/html5lib/')
+        except Exception, e:
+            print IMPORT_ERROR_MESSAGE % dict(what='html5lib')
+            traceback.print_exc(file=sys.stdout)
+
+        try:
+            import markdown
+            version = int(re.findall('^\d+', markdown.version)[0])
+            if version < 2:
+                print OLD_VERSION_ERROR % dict(what='markdown', version=markdown.version, minimum='2.0')
+                print HOW_TO_INSTALL % dict(what='markdown', where='http://www.freewisdom.org/projects/python-markdown/')
+            else:
+                print OK_MESSAGE % dict(what='markdown', version=markdown.version)
+        except ImportError:
+            print NOT_FOUND_ERROR % dict(what='markdown')
+            print HOW_TO_INSTALL % dict(what='markdown', where='http://www.freewisdom.org/projects/python-markdown/')
+        except Exception, e:
+            print IMPORT_ERROR_MESSAGE % dict(what='markdown')
+            traceback.print_exc(file=sys.stdout)
+
+        try:
+            import south
+            version = re.findall('\d+', south.__version__)
+
+            if int(version[1]) < 6 and int(version[0]) == 0:
+                print OLD_VERSION_ERROR % dict(what='south', version=south.__version__, minimum='0.6')
+                print HOW_TO_INSTALL % dict(what='south', where='http://south.aeracode.org/')
+            else:
+                print OK_MESSAGE % dict(what='south', version=south.__version__)
+
+
+        except ImportError:
+            print NOT_FOUND_ERROR % dict(what='south')
+            print HOW_TO_INSTALL % dict(what='south', where='http://south.aeracode.org/')
+        except Exception, e:
+            print IMPORT_ERROR_MESSAGE % dict(what='south')
+            traceback.print_exc(file=sys.stdout)
+
+
+        print "\n\nChecking database connection:"
+
+        try:
+            from forum.models import User
+            User.objects.all().count()
+            print "  Connection OK"
+        except Exception, e:
+            print "There seems to be a problem with your database: %s" % str(e)
+
+
+
+        from django.conf import settings
+
+        print "\n\nChecking important settings:"
+
+        if not re.match('^https?:\/\/\w+', settings.APP_URL):
+            print " Your APP_URL does not seem to be a valid url. Please fill this setting with the URL of your OSQA installation"
+        else:
+            print " APP_URL - %s" % settings.APP_URL
+            print " APP_BASE_URL - %s" % settings.APP_BASE_URL
+
+        
diff --git a/forum/modules/template_loader.py/forum/management/commands/create_extended_user.py b/forum/modules/template_loader.py/forum/management/commands/create_extended_user.py
new file mode 100644 (file)
index 0000000..4969ad2
--- /dev/null
@@ -0,0 +1,285 @@
+\r
+PG_MIGRATION_QUERY = """\r
+SELECT id AS user_ptr_id, is_approved, email_isvalid, email_key, reputation, gravatar, gold, silver, bronze, questions_per_page, last_seen, real_name, website, location, date_of_birth, about, hide_ignored_questions, tag_filter_setting INTO forum_user FROM auth_user;\r
+\r
+ALTER TABLE forum_user\r
+  ADD CONSTRAINT forum_user_pkey PRIMARY KEY(user_ptr_id);\r
+\r
+ALTER TABLE forum_user\r
+  ADD CONSTRAINT forum_user_user_ptr_id_fkey FOREIGN KEY (user_ptr_id)\r
+      REFERENCES auth_user (id) MATCH SIMPLE\r
+      ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED;\r
+\r
+ALTER TABLE forum_user\r
+  ADD CONSTRAINT forum_user_reputation_check CHECK (reputation >= 0);\r
+\r
+ALTER TABLE auth_user DROP COLUMN is_approved;\r
+ALTER TABLE auth_user DROP COLUMN email_isvalid;\r
+ALTER TABLE auth_user DROP COLUMN email_key;\r
+ALTER TABLE auth_user DROP COLUMN reputation;\r
+ALTER TABLE auth_user DROP COLUMN gravatar;\r
+ALTER TABLE auth_user DROP COLUMN gold;\r
+ALTER TABLE auth_user DROP COLUMN silver;\r
+ALTER TABLE auth_user DROP COLUMN bronze;\r
+ALTER TABLE auth_user DROP COLUMN questions_per_page;\r
+ALTER TABLE auth_user DROP COLUMN last_seen;\r
+ALTER TABLE auth_user DROP COLUMN real_name;\r
+ALTER TABLE auth_user DROP COLUMN website;\r
+ALTER TABLE auth_user DROP COLUMN "location";\r
+ALTER TABLE auth_user DROP COLUMN date_of_birth;\r
+ALTER TABLE auth_user DROP COLUMN about;\r
+ALTER TABLE auth_user DROP COLUMN hide_ignored_questions;\r
+ALTER TABLE auth_user DROP COLUMN tag_filter_setting;\r
+\r
+"""\r
+\r
+PG_FKEYS_QUERY = """\r
+\r
+ALTER TABLE "public"."activity"\r
+DROP CONSTRAINT "activity_user_id_fkey",\r
+ADD CONSTRAINT "activity_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED;\r
+\r
+ALTER TABLE "public"."answer"\r
+DROP CONSTRAINT "answer_author_id_fkey",\r
+ADD CONSTRAINT "answer_author_id_fkey" FOREIGN KEY ("author_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED,\r
+DROP CONSTRAINT "answer_deleted_by_id_fkey",\r
+ADD CONSTRAINT "answer_deleted_by_id_fkey" FOREIGN KEY ("deleted_by_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED,\r
+DROP CONSTRAINT "answer_last_edited_by_id_fkey",\r
+ADD CONSTRAINT "answer_last_edited_by_id_fkey" FOREIGN KEY ("last_edited_by_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED,\r
+DROP CONSTRAINT "answer_locked_by_id_fkey",\r
+ADD CONSTRAINT "answer_locked_by_id_fkey" FOREIGN KEY ("locked_by_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED;\r
+\r
+ALTER TABLE "public"."answer_revision"\r
+DROP CONSTRAINT "answer_revision_author_id_fkey",\r
+ADD CONSTRAINT "answer_revision_author_id_fkey" FOREIGN KEY ("author_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED;\r
+\r
+ALTER TABLE "public"."award"\r
+DROP CONSTRAINT "award_user_id_fkey",\r
+ADD CONSTRAINT "award_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED;\r
+\r
+ALTER TABLE "public"."comment"\r
+DROP CONSTRAINT "comment_user_id_fkey",\r
+ADD CONSTRAINT "comment_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED;\r
+\r
+ALTER TABLE "public"."favorite_question"\r
+DROP CONSTRAINT "favorite_question_user_id_fkey",\r
+ADD CONSTRAINT "favorite_question_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED;\r
+\r
+ALTER TABLE "public"."flagged_item"\r
+DROP CONSTRAINT "flagged_item_user_id_fkey",\r
+ADD CONSTRAINT "flagged_item_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED;\r
+\r
+ALTER TABLE "public"."forum_anonymousanswer"\r
+DROP CONSTRAINT "forum_anonymousanswer_author_id_fkey",\r
+ADD CONSTRAINT "forum_anonymousanswer_author_id_fkey" FOREIGN KEY ("author_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED;\r
+\r
+ALTER TABLE "public"."forum_anonymousquestion"\r
+DROP CONSTRAINT "forum_anonymousquestion_author_id_fkey",\r
+ADD CONSTRAINT "forum_anonymousquestion_author_id_fkey" FOREIGN KEY ("author_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED;\r
+\r
+ALTER TABLE "public"."forum_authkeyuserassociation"\r
+DROP CONSTRAINT "forum_authkeyuserassociation_user_id_fkey",\r
+ADD CONSTRAINT "forum_authkeyuserassociation_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED;\r
+\r
+ALTER TABLE "public"."forum_markedtag"\r
+DROP CONSTRAINT "forum_markedtag_user_id_fkey",\r
+ADD CONSTRAINT "forum_markedtag_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED;\r
+\r
+ALTER TABLE "public"."forum_questionsubscription"\r
+DROP CONSTRAINT "forum_questionsubscription_user_id_fkey",\r
+ADD CONSTRAINT "forum_questionsubscription_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED;\r
+\r
+ALTER TABLE "public"."forum_subscriptionsettings"\r
+DROP CONSTRAINT "forum_subscriptionsettings_user_id_fkey",\r
+ADD CONSTRAINT "forum_subscriptionsettings_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED;\r
+\r
+ALTER TABLE "public"."forum_validationhash"\r
+DROP CONSTRAINT "forum_validationhash_user_id_fkey",\r
+ADD CONSTRAINT "forum_validationhash_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED;\r
+\r
+ALTER TABLE "public"."question"\r
+DROP CONSTRAINT "question_author_id_fkey",\r
+ADD CONSTRAINT "question_author_id_fkey" FOREIGN KEY ("author_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED,\r
+DROP CONSTRAINT "question_closed_by_id_fkey",\r
+ADD CONSTRAINT "question_closed_by_id_fkey" FOREIGN KEY ("closed_by_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED,\r
+DROP CONSTRAINT "question_deleted_by_id_fkey",\r
+ADD CONSTRAINT "question_deleted_by_id_fkey" FOREIGN KEY ("deleted_by_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED,\r
+DROP CONSTRAINT "question_last_activity_by_id_fkey",\r
+ADD CONSTRAINT "question_last_activity_by_id_fkey" FOREIGN KEY ("last_activity_by_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED,\r
+DROP CONSTRAINT "question_last_edited_by_id_fkey",\r
+ADD CONSTRAINT "question_last_edited_by_id_fkey" FOREIGN KEY ("last_edited_by_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED,\r
+DROP CONSTRAINT "question_locked_by_id_fkey",\r
+ADD CONSTRAINT "question_locked_by_id_fkey" FOREIGN KEY ("locked_by_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED;\r
+\r
+ALTER TABLE "public"."question_followed_by"\r
+DROP CONSTRAINT "question_followed_by_user_id_fkey",\r
+ADD CONSTRAINT "question_followed_by_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED;\r
+\r
+ALTER TABLE "public"."question_revision"\r
+DROP CONSTRAINT "question_revision_author_id_fkey",\r
+ADD CONSTRAINT "question_revision_author_id_fkey" FOREIGN KEY ("author_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED;\r
+\r
+ALTER TABLE "public"."repute"\r
+DROP CONSTRAINT "repute_user_id_fkey",\r
+ADD CONSTRAINT "repute_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED;\r
+\r
+ALTER TABLE "public"."tag"\r
+DROP CONSTRAINT "tag_created_by_id_fkey",\r
+ADD CONSTRAINT "tag_created_by_id_fkey" FOREIGN KEY ("created_by_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED,\r
+DROP CONSTRAINT "tag_deleted_by_id_fkey",\r
+ADD CONSTRAINT "tag_deleted_by_id_fkey" FOREIGN KEY ("deleted_by_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED;\r
+\r
+ALTER TABLE "public"."vote"\r
+DROP CONSTRAINT "vote_user_id_fkey",\r
+ADD CONSTRAINT "vote_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."forum_user" (user_ptr_id) ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED;\r
+\r
+"""\r
+\r
+MYSQL_MIGRATION_QUERY = """\r
+CREATE TABLE `forum_user` (\r
+  `user_ptr_id` int(11) NOT NULL,\r
+  `is_approved` tinyint(1) NOT NULL,\r
+  `email_isvalid` tinyint(1) NOT NULL,\r
+  `email_key` varchar(32) DEFAULT NULL,\r
+  `reputation` int(10) unsigned NOT NULL,\r
+  `gravatar` varchar(32) NOT NULL,\r
+  `gold` smallint(6) NOT NULL,\r
+  `silver` smallint(6) NOT NULL,\r
+  `bronze` smallint(6) NOT NULL,\r
+  `questions_per_page` smallint(6) NOT NULL,\r
+  `last_seen` datetime NOT NULL,\r
+  `real_name` varchar(100) NOT NULL,\r
+  `website` varchar(200) NOT NULL,\r
+  `location` varchar(100) NOT NULL,\r
+  `date_of_birth` date DEFAULT NULL,\r
+  `about` longtext NOT NULL,\r
+  `hide_ignored_questions` tinyint(1) NOT NULL,\r
+  `tag_filter_setting` varchar(16) NOT NULL,\r
+  PRIMARY KEY (`user_ptr_id`),\r
+  CONSTRAINT `user_ptr_id_refs_id_71071d7` FOREIGN KEY (`user_ptr_id`) REFERENCES `auth_user` (`id`)\r
+) ENGINE=InnoDB DEFAULT CHARSET=utf8\r
+SELECT id AS user_ptr_id, is_approved, email_isvalid, email_key, reputation, gravatar, gold, silver, bronze, questions_per_page,\r
+       last_seen, real_name, website, location, date_of_birth, about, hide_ignored_questions, tag_filter_setting FROM auth_user;\r
+\r
+ALTER TABLE `auth_user`\r
+DROP COLUMN `is_approved`,\r
+DROP COLUMN `email_isvalid`,\r
+DROP COLUMN `email_key`,\r
+DROP COLUMN `reputation`,\r
+DROP COLUMN `gravatar`,\r
+DROP COLUMN `gold`,\r
+DROP COLUMN `silver`,\r
+DROP COLUMN `bronze`,\r
+DROP COLUMN `questions_per_page`,\r
+DROP COLUMN `last_seen`,\r
+DROP COLUMN `real_name`,\r
+DROP COLUMN `website`,\r
+DROP COLUMN `location`,\r
+DROP COLUMN `date_of_birth`,\r
+DROP COLUMN `about`,\r
+DROP COLUMN `hide_ignored_questions`,\r
+DROP COLUMN `tag_filter_setting`;\r
+\r
+"""\r
+\r
+MYSQL_FKEYS_QUERY = """\r
+\r
+ALTER TABLE `activity` DROP FOREIGN KEY `user_id_refs_id_47c8583f`;\r
+ALTER TABLE `activity` ADD CONSTRAINT `user_id_refs_user_ptr_id_62ae9785` FOREIGN KEY (`user_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+\r
+ALTER TABLE `answer` DROP FOREIGN KEY `author_id_refs_id_192b0170`;\r
+ALTER TABLE `answer` ADD CONSTRAINT `author_id_refs_user_ptr_id_9681994` FOREIGN KEY (`author_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+ALTER TABLE `answer` DROP FOREIGN KEY `deleted_by_id_refs_id_192b0170`;\r
+ALTER TABLE `answer` ADD CONSTRAINT `deleted_by_id_refs_user_ptr_id_9681994` FOREIGN KEY (`deleted_by_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+ALTER TABLE `answer` DROP FOREIGN KEY `last_edited_by_id_refs_id_192b0170`;\r
+ALTER TABLE `answer` ADD CONSTRAINT `last_edited_by_id_refs_user_ptr_id_9681994` FOREIGN KEY (`last_edited_by_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+ALTER TABLE `answer` DROP FOREIGN KEY `locked_by_id_refs_id_192b0170`;\r
+ALTER TABLE `answer` ADD CONSTRAINT `locked_by_id_refs_user_ptr_id_9681994` FOREIGN KEY (`locked_by_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+\r
+ALTER TABLE `answer_revision` DROP FOREIGN KEY `author_id_refs_id_3ccc055f`;\r
+ALTER TABLE `answer_revision` ADD CONSTRAINT `author_id_refs_user_ptr_id_331f0123` FOREIGN KEY (`author_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+\r
+ALTER TABLE `award` DROP FOREIGN KEY `user_id_refs_id_2d83e9b6`;\r
+ALTER TABLE `award` ADD CONSTRAINT `user_id_refs_user_ptr_id_1b2d0192` FOREIGN KEY (`user_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+\r
+ALTER TABLE `comment` DROP FOREIGN KEY `user_id_refs_id_6be725e8`;\r
+ALTER TABLE `comment` ADD CONSTRAINT `user_id_refs_user_ptr_id_1ac2320c` FOREIGN KEY (`user_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+\r
+ALTER TABLE `favorite_question` DROP FOREIGN KEY `user_id_refs_id_52853822`;\r
+ALTER TABLE `favorite_question` ADD CONSTRAINT `user_id_refs_user_ptr_id_3f419c1a` FOREIGN KEY (`user_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+\r
+ALTER TABLE `flagged_item` DROP FOREIGN KEY `user_id_refs_id_35e3c608`;\r
+ALTER TABLE `flagged_item` ADD CONSTRAINT `user_id_refs_user_ptr_id_1ce834d4` FOREIGN KEY (`user_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+\r
+ALTER TABLE `forum_anonymousanswer` DROP FOREIGN KEY `author_id_refs_id_13fb542e`;\r
+ALTER TABLE `forum_anonymousanswer` ADD CONSTRAINT `author_id_refs_user_ptr_id_6b5b476a` FOREIGN KEY (`author_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+\r
+ALTER TABLE `forum_anonymousquestion` DROP FOREIGN KEY `author_id_refs_id_7511a98a`;\r
+ALTER TABLE `forum_anonymousquestion` ADD CONSTRAINT `author_id_refs_user_ptr_id_104edd52` FOREIGN KEY (`author_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+\r
+ALTER TABLE `forum_authkeyuserassociation` DROP FOREIGN KEY `user_id_refs_id_2c2a6b01`;\r
+ALTER TABLE `forum_authkeyuserassociation` ADD CONSTRAINT `user_id_refs_user_ptr_id_3f0ec0c3` FOREIGN KEY (`user_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+\r
+ALTER TABLE `forum_markedtag` DROP FOREIGN KEY `user_id_refs_id_23b833bd`;\r
+ALTER TABLE `forum_markedtag` ADD CONSTRAINT `user_id_refs_user_ptr_id_5a13f081` FOREIGN KEY (`user_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+\r
+ALTER TABLE `forum_questionsubscription` DROP FOREIGN KEY `user_id_refs_id_18e1489`;\r
+ALTER TABLE `forum_questionsubscription` ADD CONSTRAINT `user_id_refs_user_ptr_id_521b19ad` FOREIGN KEY (`user_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+\r
+ALTER TABLE `forum_subscriptionsettings` DROP FOREIGN KEY `user_id_refs_id_35edacb4`;\r
+ALTER TABLE `forum_subscriptionsettings` ADD CONSTRAINT `user_id_refs_user_ptr_id_1bc4fc70` FOREIGN KEY (`user_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+\r
+ALTER TABLE `forum_validationhash` DROP FOREIGN KEY `user_id_refs_id_2c2d214b`;\r
+ALTER TABLE `forum_validationhash` ADD CONSTRAINT `user_id_refs_user_ptr_id_4e5b2d6f` FOREIGN KEY (`user_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+\r
+ALTER TABLE `question` DROP FOREIGN KEY `author_id_refs_id_56e9d00c`;\r
+ALTER TABLE `question` ADD CONSTRAINT `author_id_refs_user_ptr_id_60d41818` FOREIGN KEY (`author_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+ALTER TABLE `question` DROP FOREIGN KEY `closed_by_id_refs_id_56e9d00c`;\r
+ALTER TABLE `question` ADD CONSTRAINT `closed_by_id_refs_user_ptr_id_60d41818` FOREIGN KEY (`closed_by_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+ALTER TABLE `question` DROP FOREIGN KEY `deleted_by_id_refs_id_56e9d00c`;\r
+ALTER TABLE `question` ADD CONSTRAINT `deleted_by_id_refs_user_ptr_id_60d41818` FOREIGN KEY (`deleted_by_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+ALTER TABLE `question` DROP FOREIGN KEY `last_activity_by_id_refs_id_56e9d00c`;\r
+ALTER TABLE `question` ADD CONSTRAINT `last_activity_by_id_refs_user_ptr_id_60d41818` FOREIGN KEY (`last_activity_by_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+ALTER TABLE `question` DROP FOREIGN KEY `last_edited_by_id_refs_id_56e9d00c`;\r
+ALTER TABLE `question` ADD CONSTRAINT `last_edited_by_id_refs_user_ptr_id_60d41818` FOREIGN KEY (`last_edited_by_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+ALTER TABLE `question` DROP FOREIGN KEY `locked_by_id_refs_id_56e9d00c`;\r
+ALTER TABLE `question` ADD CONSTRAINT `locked_by_id_refs_user_ptr_id_60d41818` FOREIGN KEY (`locked_by_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+\r
+ALTER TABLE `question_followed_by` DROP FOREIGN KEY `user_id_refs_id_6d30712d`;\r
+ALTER TABLE `question_followed_by` ADD CONSTRAINT `user_id_refs_user_ptr_id_615e65af` FOREIGN KEY (`user_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+\r
+ALTER TABLE `question_revision` DROP FOREIGN KEY `author_id_refs_id_4f88024f`;\r
+ALTER TABLE `question_revision` ADD CONSTRAINT `author_id_refs_user_ptr_id_42e3d48d` FOREIGN KEY (`author_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+\r
+ALTER TABLE `repute` DROP FOREIGN KEY `user_id_refs_id_5a426cd`;\r
+ALTER TABLE `repute` ADD CONSTRAINT `user_id_refs_user_ptr_id_5ea9540f` FOREIGN KEY (`user_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+\r
+ALTER TABLE `tag` DROP FOREIGN KEY `created_by_id_refs_id_47205d6d`;\r
+ALTER TABLE `tag` ADD CONSTRAINT `created_by_id_refs_user_ptr_id_417f3449` FOREIGN KEY (`created_by_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+ALTER TABLE `tag` DROP FOREIGN KEY `deleted_by_id_refs_id_47205d6d`;\r
+ALTER TABLE `tag` ADD CONSTRAINT `deleted_by_id_refs_user_ptr_id_417f3449` FOREIGN KEY (`deleted_by_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+\r
+ALTER TABLE `vote` DROP FOREIGN KEY `user_id_refs_id_760a4df0`;\r
+ALTER TABLE `vote` ADD CONSTRAINT `user_id_refs_user_ptr_id_18723e34` FOREIGN KEY (`user_id`) REFERENCES `forum_user` (`user_ptr_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;\r
+\r
+"""\r
+\r
+from django.core.management.base import NoArgsCommand\r
+from django.db import connection, transaction\r
+from django.conf import settings\r
+\r
+class Command(NoArgsCommand):\r
+    def handle_noargs(self, **options):\r
+        if settings.DATABASE_ENGINE in ('postgresql_psycopg2', 'postgresql', ):\r
+            migration_query = PG_MIGRATION_QUERY\r
+            fkeys_query = PG_FKEYS_QUERY\r
+        elif settings.DATABASE_ENGINE == 'mysql':\r
+            migration_query = MYSQL_MIGRATION_QUERY\r
+            fkeys_query = MYSQL_FKEYS_QUERY\r
+        else:\r
+            raise Exception("Database backend not suported by this migration command")\r
+\r
+        cursor = connection.cursor()\r
+        cursor.execute(migration_query)\r
+        cursor.execute(fkeys_query)\r
+        transaction.commit_unless_managed()
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/management/commands/create_subscriptions.py b/forum/modules/template_loader.py/forum/management/commands/create_subscriptions.py
new file mode 100644 (file)
index 0000000..b97c970
--- /dev/null
@@ -0,0 +1,15 @@
+from forum.models import User, SubscriptionSettings, QuestionSubscription\r
+from django.core.management.base import NoArgsCommand\r
+\r
+class Command(NoArgsCommand):\r
+    def handle_noargs(self, **options):\r
+        users = User.objects.all()\r
+        for u in users:\r
+            s = SubscriptionSettings(user=u)\r
+            s.save()\r
+\r
+            user_questions = u.questions.all()\r
+\r
+            for q in user_questions:\r
+                sub = QuestionSubscription(user=u, question=q)\r
+                sub.save()
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/management/commands/message_to_everyone.py b/forum/modules/template_loader.py/forum/management/commands/message_to_everyone.py
new file mode 100644 (file)
index 0000000..ea7b41a
--- /dev/null
@@ -0,0 +1,12 @@
+from django.core.management.base import NoArgsCommand
+from forum.models import User
+import sys
+
+class Command(NoArgsCommand):
+    def handle_noargs(self, **options):
+        msg = None
+        if msg == None:
+            print 'to run this command, please first edit the file %s' % __file__
+            sys.exit(1)
+        for u in User.objects.all():
+            u.message_set.create(message = msg % u.username)
diff --git a/forum/modules/template_loader.py/forum/management/commands/sample_command.py b/forum/modules/template_loader.py/forum/management/commands/sample_command.py
new file mode 100644 (file)
index 0000000..55e6723
--- /dev/null
@@ -0,0 +1,7 @@
+from django.core.management.base import NoArgsCommand
+from forum.models import Comment
+
+class Command(NoArgsCommand):
+    def handle_noargs(self, **options):
+        objs = Comment.objects.all()
+        print objs
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/management/commands/send_email_alerts.py b/forum/modules/template_loader.py/forum/management/commands/send_email_alerts.py
new file mode 100644 (file)
index 0000000..85b83fa
--- /dev/null
@@ -0,0 +1,114 @@
+import datetime
+from forum.models import *
+from forum import settings
+from django.db import models
+from forum.utils.mail import send_template_email
+from django.core.management.base import NoArgsCommand
+from forum.settings.email import EMAIL_DIGEST_FLAG
+from django.utils import translation
+import logging
+
+SHOW_N_MORE_ACTIVE_NEW_MEMBERS = 5
+SUB_QUESTION_LIST_LENGTH = 5
+TRY_N_USER_TAGS = 5
+
+
+
+class DigestQuestionsIndex(object):
+    def __init__(self, from_date):
+        self.from_date = from_date
+
+        new_questions = Question.objects.filter_state(deleted=False).\
+            filter(added_at__gt=from_date).\
+            annotate(n_actions=models.Count('actions')).\
+            annotate(child_count=models.Count('all_children'))
+
+        hotness = lambda q: 3*q.child_count + q.n_actions
+
+        for q in new_questions:
+            q.hotness=hotness(q)
+
+        self.questions = sorted(new_questions, lambda q1, q2: q2.hotness - q1.hotness)
+        self.count = len(self.questions)
+
+    def unseen_question(self, user, question):
+        try:
+            subscription = QuestionSubscription.objects.get(question=q, user=user)
+        except:
+            subscription = None
+
+        return (not subscription) or subscription.last_view < q.last_activity_at
+
+    def get_for_user(self, user):
+        user_tags = list(user.marked_tags.filter(user_selections__reason='good'))
+
+        if len(user_tags) < TRY_N_USER_TAGS:
+            user_tags += list(Tag.objects.filter(models.Q(nodes__author=user) | models.Q(nodes__children__author=user)) \
+                .annotate(user_tag_usage_count=models.Count('name')).order_by('-user_tag_usage_count')[:TRY_N_USER_TAGS - len(user_tags)])
+
+        user_tag_names = set([t.name for t in user_tags])
+
+
+        subscriptions = user.subscriptions.filter(added_at__lt=self.from_date, last_activity_at__gt=models.F('questionsubscription__last_view')
+                                                  ).order_by('-questionsubscription__last_view')[:SUB_QUESTION_LIST_LENGTH]
+
+        unseen_questions = [q for q in self.questions if self.unseen_question(user, q)]
+
+        interesting = []
+
+        for q in unseen_questions:
+            if len(set(q.tagname_list()) & user_tag_names): interesting.append(q)
+
+
+        may_help = []
+        if len(interesting):
+            if len(interesting) > SUB_QUESTION_LIST_LENGTH:
+                may_help = interesting[SUB_QUESTION_LIST_LENGTH:][-SUB_QUESTION_LIST_LENGTH:]
+                interesting = interesting[:SUB_QUESTION_LIST_LENGTH]
+        else:
+            interesting = unseen_questions[:SUB_QUESTION_LIST_LENGTH]
+
+        return {'interesting': interesting, 'may_help': may_help, 'subscriptions': subscriptions}
+
+
+
+
+class Command(NoArgsCommand):
+    def handle_noargs(self, **options):
+        try:
+            translation.activate(settings.LANGUAGE_CODE)
+        except:
+            logging.error("Unable to set the locale in the send emails cron job")
+
+        digest_control = EMAIL_DIGEST_FLAG.value
+
+        if digest_control is None:
+            digest_control = {
+            'LAST_DAILY': datetime.datetime.now() - datetime.timedelta(days=1),
+            'LAST_WEEKLY': datetime.datetime.now() - datetime.timedelta(days=1),
+            }
+
+        from_date = digest_control['LAST_DAILY']
+        digest_control['LAST_DAILY'] = datetime.datetime.now()
+
+        EMAIL_DIGEST_FLAG.set_value(digest_control)
+
+        users = User.objects.filter(subscription_settings__enable_notifications=True, subscription_settings__send_digest=True)
+        new_members = User.objects.filter(is_active=True, date_joined__gt=from_date).annotate(n_actions=models.Count('actions')).order_by('-n_actions')
+
+        new_member_count = new_members.count()
+
+        if new_member_count >= SHOW_N_MORE_ACTIVE_NEW_MEMBERS:
+            new_members = new_members[:SHOW_N_MORE_ACTIVE_NEW_MEMBERS]
+            show_all_users = True
+        else:
+            show_all_users = False
+
+        digest = DigestQuestionsIndex(from_date)
+
+        if (not new_member_count) and (not digest.count):
+            return
+
+        send_template_email(users, "notifications/digest.html", locals())
+
+
diff --git a/forum/modules/template_loader.py/forum/markdownext/__init__.py b/forum/modules/template_loader.py/forum/markdownext/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/forum/modules/template_loader.py/forum/markdownext/mdx_limitedsyntax.py b/forum/modules/template_loader.py/forum/markdownext/mdx_limitedsyntax.py
new file mode 100644 (file)
index 0000000..6a6dac5
--- /dev/null
@@ -0,0 +1,11 @@
+import markdown\r
+from django.utils.safestring import mark_safe\r
+from django.utils.html import strip_tags\r
+from forum.utils.html import sanitize_html\r
+\r
+class LimitedSyntaxExtension(markdown.Extension):\r
+    def extendMarkdown(self, md, md_globals):\r
+        del md.inlinePatterns["image_reference"]\r
+\r
+def makeExtension(configs=None) :\r
+    return LimitedSyntaxExtension(configs=configs)\r
diff --git a/forum/modules/template_loader.py/forum/markdownext/mdx_settingsparser.py b/forum/modules/template_loader.py/forum/markdownext/mdx_settingsparser.py
new file mode 100644 (file)
index 0000000..9d0c69f
--- /dev/null
@@ -0,0 +1,46 @@
+from os import linesep
+from csv import reader, QUOTE_NONE
+import markdown
+from markdown import Extension
+from markdown.preprocessors import Preprocessor
+import re
+
+from forum import settings
+
+class SettingsExtension(markdown.Extension):
+    def __init__(self, configs):
+        self.configs = {} # settings.REP_TO_VOTE_UP}
+        for key, value in configs:
+            self.config[key] = value
+
+        # self.extendMarkdown(markdown.Markdown()., config)
+
+    def reset(self):
+        pass
+
+    def extendMarkdown(self, md, md_globals):
+        md.registerExtension(self)
+        self.parser = md.parser
+        md.preprocessors.add('MinRep', SettingsPre(self), '_begin')
+
+SETTING_RE = re.compile(r'\|[A-Z_]+\|')
+
+def setting_rep_callback(m):
+    setting_name = m.group(0).strip('|')
+    if hasattr(settings, setting_name):
+        return unicode(getattr(settings, setting_name))
+    else:
+        return ''
+
+
+class SettingsPre(Preprocessor):
+    def run(self, lines):
+        new_lines = []
+        for line in lines:
+            new_lines.append(SETTING_RE.sub(setting_rep_callback, line))
+
+        return new_lines
+
+
+def makeExtension(configs=None) :
+    return SettingsExtension(configs=configs)
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/markdownext/mdx_urlize.py b/forum/modules/template_loader.py/forum/markdownext/mdx_urlize.py
new file mode 100644 (file)
index 0000000..94fa516
--- /dev/null
@@ -0,0 +1,44 @@
+import markdown
+
+# Global Vars
+URLIZE_RE = '(%s)' % '|'.join([
+    r'<(?:f|ht)tps?://[^>]*>',
+    r'\b(?:f|ht)tps?://[^)<>\s]+[^.,)<>\s]',
+    r'\bwww\.[^)<>\s]+[^.,)<>\s]',
+    r'[^(<\s]+\.(?:com|net|org)\b',
+])
+
+class UrlizePattern(markdown.inlinepatterns.Pattern):
+    """ Return a link Element given an autolink (`http://example/com`). """
+    def handleMatch(self, m):
+        url = m.group(2)
+        
+        if url.startswith('<'):
+            url = url[1:-1]
+            
+        text = url
+        
+        if not url.split('://')[0] in ('http','https','ftp'):
+            if '@' in url and not '/' in url:
+                url = 'mailto:' + url
+            else:
+                url = 'http://' + url
+    
+        el = markdown.etree.Element("a")
+        el.set('href', url)
+        el.text = markdown.AtomicString(text)
+        return el
+
+class UrlizeExtension(markdown.Extension):
+    """ Urlize Extension for Python-Markdown. """
+
+    def extendMarkdown(self, md, md_globals):
+        """ Replace autolink with UrlizePattern """
+        md.inlinePatterns['autolink'] = UrlizePattern(URLIZE_RE, md)
+
+def makeExtension(configs=None):
+    return UrlizeExtension(configs=configs)
+
+if __name__ == "__main__":
+    import doctest
+    doctest.testmod()
diff --git a/forum/modules/template_loader.py/forum/middleware/__init__.py b/forum/modules/template_loader.py/forum/middleware/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/forum/modules/template_loader.py/forum/middleware/anon_user.py b/forum/modules/template_loader.py/forum/middleware/anon_user.py
new file mode 100644 (file)
index 0000000..26c138c
--- /dev/null
@@ -0,0 +1,35 @@
+from django.http import HttpResponseRedirect
+from forum.forms import get_next_url
+from django.utils.translation import ugettext as _
+from forum.user_messages import create_message, get_and_delete_messages
+from forum import settings
+from django.core.urlresolvers import reverse
+import logging
+
+class AnonymousMessageManager(object):
+    def __init__(self,request):
+        self.request = request
+    def create(self,message=''):
+        create_message(self.request,message)  
+    def get_and_delete(self):
+        messages = get_and_delete_messages(self.request)
+        return messages
+
+def dummy_deepcopy(*arg):
+    """this is necessary to prevent deepcopy() on anonymous user object
+    that now contains reference to request, which cannot be deepcopied
+    """
+    return None
+
+class ConnectToSessionMessagesMiddleware(object):
+    def process_request(self, request):
+        if not request.user.is_authenticated():
+            request.user.__deepcopy__ = dummy_deepcopy #plug on deepcopy which may be called by django db "driver"
+            request.user.message_set = AnonymousMessageManager(request) #here request is linked to anon user
+            request.user.get_and_delete_messages = request.user.message_set.get_and_delete
+
+            #also set the first greeting one time per session only
+            if 'greeting_set' not in request.session:
+                request.session['greeting_set'] = True
+                msg = _('First time here? Check out the <a href="%s">FAQ</a>!') % reverse('faq')
+                request.user.message_set.create(message=msg)
diff --git a/forum/modules/template_loader.py/forum/middleware/cancel.py b/forum/modules/template_loader.py/forum/middleware/cancel.py
new file mode 100644 (file)
index 0000000..2d78a17
--- /dev/null
@@ -0,0 +1,15 @@
+from django.http import HttpResponseRedirect
+from forum.forms import get_next_url
+import logging
+class CancelActionMiddleware(object):
+    def process_view(self, request, view_func, view_args, view_kwargs):
+        if 'cancel' in request.REQUEST:
+            #todo use session messages for the anonymous users
+            try:
+                msg = getattr(view_func,'CANCEL_MESSAGE')
+            except AttributeError:
+                msg = 'action canceled'
+            request.user.message_set.create(message=msg)
+            return HttpResponseRedirect(get_next_url(request))
+        else:
+            return None
diff --git a/forum/modules/template_loader.py/forum/middleware/extended_user.py b/forum/modules/template_loader.py/forum/middleware/extended_user.py
new file mode 100644 (file)
index 0000000..dfe7163
--- /dev/null
@@ -0,0 +1,27 @@
+from django.contrib.auth.middleware import AuthenticationMiddleware\r
+from django.contrib.auth import logout\r
+from forum.models.user import AnonymousUser\r
+from forum.views.auth import forward_suspended_user\r
+import logging\r
+\r
+class ExtendedUser(AuthenticationMiddleware):\r
+    def process_request(self, request):\r
+        super(ExtendedUser, self).process_request(request)\r
+        if request.user.is_authenticated():\r
+            try:\r
+                request.user = request.user.user\r
+\r
+                if request.user.is_suspended():\r
+                    user = request.user\r
+                    logout(request)\r
+                    return forward_suspended_user(request, user)\r
+\r
+                return None\r
+            except Exception, e:\r
+                import traceback\r
+                logging.error("Unable to convert auth_user %s to forum_user: \n%s" % (\r
+                    request.user.id, traceback.format_exc()\r
+                ))\r
+\r
+        request.user = AnonymousUser()\r
+        return None
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/middleware/request_utils.py b/forum/modules/template_loader.py/forum/middleware/request_utils.py
new file mode 100644 (file)
index 0000000..bbccbf7
--- /dev/null
@@ -0,0 +1,18 @@
+from forum.settings import MAINTAINANCE_MODE, APP_LOGO, APP_TITLE\r
+\r
+from forum.http_responses import HttpResponseServiceUnavailable\r
+\r
+class RequestUtils(object):\r
+    def process_request(self, request):\r
+        if MAINTAINANCE_MODE.value is not None and isinstance(MAINTAINANCE_MODE.value.get('allow_ips', None), list):\r
+            ip = request.META['REMOTE_ADDR']\r
+\r
+            if not ip in MAINTAINANCE_MODE.value['allow_ips']:\r
+                return HttpResponseServiceUnavailable(MAINTAINANCE_MODE.value.get('message', ''))\r
+\r
+        if request.session.get('redirect_POST_data', None):\r
+            request.POST = request.session.pop('redirect_POST_data')\r
+            request.META['REQUEST_METHOD'] = "POST"\r
+\r
+        self.request = request\r
+        return None
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/migrations/0001_initial.py b/forum/modules/template_loader.py/forum/migrations/0001_initial.py
new file mode 100644 (file)
index 0000000..5dbd4a2
--- /dev/null
@@ -0,0 +1,764 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import SchemaMigration\r
+from django.db import models\r
+\r
+class Migration(SchemaMigration):\r
+    \r
+    def forwards(self, orm):\r
+        \r
+        # Adding model 'User'\r
+        db.create_table('forum_user', (\r
+            ('website', self.gf('django.db.models.fields.URLField')(max_length=200, blank=True)),\r
+            ('user_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['auth.User'], unique=True, primary_key=True)),\r
+            ('hide_ignored_questions', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('is_approved', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('email_isvalid', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('real_name', self.gf('django.db.models.fields.CharField')(max_length=100, blank=True)),\r
+            ('about', self.gf('django.db.models.fields.TextField')(blank=True)),\r
+            ('silver', self.gf('django.db.models.fields.SmallIntegerField')(default=0)),\r
+            ('date_of_birth', self.gf('django.db.models.fields.DateField')(null=True, blank=True)),\r
+            ('reputation', self.gf('django.db.models.fields.PositiveIntegerField')(default=1)),\r
+            ('gravatar', self.gf('django.db.models.fields.CharField')(max_length=32)),\r
+            ('location', self.gf('django.db.models.fields.CharField')(max_length=100, blank=True)),\r
+            ('tag_filter_setting', self.gf('django.db.models.fields.CharField')(default='ignored', max_length=16)),\r
+            ('gold', self.gf('django.db.models.fields.SmallIntegerField')(default=0)),\r
+            ('last_seen', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+            ('email_key', self.gf('django.db.models.fields.CharField')(max_length=32, null=True)),\r
+            ('bronze', self.gf('django.db.models.fields.SmallIntegerField')(default=0)),\r
+            ('questions_per_page', self.gf('django.db.models.fields.SmallIntegerField')(default=10)),\r
+        ))\r
+        db.send_create_signal('forum', ['User'])\r
+\r
+        # Adding model 'Activity'\r
+        db.create_table(u'activity', (\r
+            ('is_auditted', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('object_id', self.gf('django.db.models.fields.PositiveIntegerField')()),\r
+            ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.User'])),\r
+            ('content_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['contenttypes.ContentType'])),\r
+            ('active_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('activity_type', self.gf('django.db.models.fields.SmallIntegerField')()),\r
+        ))\r
+        db.send_create_signal('forum', ['Activity'])\r
+\r
+        # Adding model 'SubscriptionSettings'\r
+        db.create_table('forum_subscriptionsettings', (\r
+            ('questions_asked', self.gf('django.db.models.fields.BooleanField')(default=True, blank=True)),\r
+            ('questions_viewed', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('notify_comments', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('new_question', self.gf('django.db.models.fields.CharField')(default='d', max_length=1)),\r
+            ('all_questions', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('new_question_watched_tags', self.gf('django.db.models.fields.CharField')(default='i', max_length=1)),\r
+            ('questions_answered', self.gf('django.db.models.fields.BooleanField')(default=True, blank=True)),\r
+            ('notify_comments_own_post', self.gf('django.db.models.fields.BooleanField')(default=True, blank=True)),\r
+            ('questions_commented', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('subscribed_questions', self.gf('django.db.models.fields.CharField')(default='i', max_length=1)),\r
+            ('notify_reply_to_comments', self.gf('django.db.models.fields.BooleanField')(default=True, blank=True)),\r
+            ('member_joins', self.gf('django.db.models.fields.CharField')(default='n', max_length=1)),\r
+            ('user', self.gf('django.db.models.fields.related.OneToOneField')(related_name='subscription_settings', unique=True, to=orm['forum.User'])),\r
+            ('notify_answers', self.gf('django.db.models.fields.BooleanField')(default=True, blank=True)),\r
+            ('enable_notifications', self.gf('django.db.models.fields.BooleanField')(default=True, blank=True)),\r
+            ('all_questions_watched_tags', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('notify_accepted', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+        ))\r
+        db.send_create_signal('forum', ['SubscriptionSettings'])\r
+\r
+        # Adding model 'ValidationHash'\r
+        db.create_table('forum_validationhash', (\r
+            ('hash_code', self.gf('django.db.models.fields.CharField')(unique=True, max_length=255)),\r
+            ('seed', self.gf('django.db.models.fields.CharField')(max_length=12)),\r
+            ('expiration', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime(2010, 4, 7, 10, 36, 23, 812000))),\r
+            ('type', self.gf('django.db.models.fields.CharField')(max_length=12)),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.User'])),\r
+        ))\r
+        db.send_create_signal('forum', ['ValidationHash'])\r
+\r
+        # Adding unique constraint on 'ValidationHash', fields ['user', 'type']\r
+        db.create_unique('forum_validationhash', ['user_id', 'type'])\r
+\r
+        # Adding model 'AuthKeyUserAssociation'\r
+        db.create_table('forum_authkeyuserassociation', (\r
+            ('added_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+            ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='auth_keys', to=orm['forum.User'])),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('key', self.gf('django.db.models.fields.CharField')(unique=True, max_length=255)),\r
+            ('provider', self.gf('django.db.models.fields.CharField')(max_length=64)),\r
+        ))\r
+        db.send_create_signal('forum', ['AuthKeyUserAssociation'])\r
+\r
+        # Adding model 'Vote'\r
+        db.create_table(u'vote', (\r
+            ('object_id', self.gf('django.db.models.fields.PositiveIntegerField')()),\r
+            ('voted_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+            ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='votes', to=orm['forum.User'])),\r
+            ('content_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['contenttypes.ContentType'])),\r
+            ('vote', self.gf('django.db.models.fields.SmallIntegerField')()),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+        ))\r
+        db.send_create_signal('forum', ['Vote'])\r
+\r
+        # Adding unique constraint on 'Vote', fields ['content_type', 'object_id', 'user']\r
+        db.create_unique(u'vote', ['content_type_id', 'object_id', 'user_id'])\r
+\r
+        # Adding model 'FlaggedItem'\r
+        db.create_table(u'flagged_item', (\r
+            ('object_id', self.gf('django.db.models.fields.PositiveIntegerField')()),\r
+            ('flagged_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('content_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['contenttypes.ContentType'])),\r
+            ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='flaggeditems', to=orm['forum.User'])),\r
+        ))\r
+        db.send_create_signal('forum', ['FlaggedItem'])\r
+\r
+        # Adding unique constraint on 'FlaggedItem', fields ['content_type', 'object_id', 'user']\r
+        db.create_unique(u'flagged_item', ['content_type_id', 'object_id', 'user_id'])\r
+\r
+        # Adding model 'Comment'\r
+        db.create_table(u'comment', (\r
+            ('comment', self.gf('django.db.models.fields.CharField')(max_length=300)),\r
+            ('object_id', self.gf('django.db.models.fields.PositiveIntegerField')()),\r
+            ('added_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+            ('content_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['contenttypes.ContentType'])),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='comments', to=orm['forum.User'])),\r
+        ))\r
+        db.send_create_signal('forum', ['Comment'])\r
+\r
+        # Adding model 'Tag'\r
+        db.create_table(u'tag', (\r
+            ('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=255)),\r
+            ('deleted', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('created_by', self.gf('django.db.models.fields.related.ForeignKey')(related_name='created_tags', to=orm['forum.User'])),\r
+            ('deleted_by', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='deleted_tags', null=True, to=orm['forum.User'])),\r
+            ('used_count', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),\r
+            ('deleted_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+        ))\r
+        db.send_create_signal('forum', ['Tag'])\r
+\r
+        # Adding model 'MarkedTag'\r
+        db.create_table('forum_markedtag', (\r
+            ('reason', self.gf('django.db.models.fields.CharField')(max_length=16)),\r
+            ('tag', self.gf('django.db.models.fields.related.ForeignKey')(related_name='user_selections', to=orm['forum.Tag'])),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='tag_selections', to=orm['forum.User'])),\r
+        ))\r
+        db.send_create_signal('forum', ['MarkedTag'])\r
+\r
+        # Adding model 'Question'\r
+        db.create_table(u'question', (\r
+            ('wiki', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('vote_up_count', self.gf('django.db.models.fields.IntegerField')(default=0)),\r
+            ('answer_accepted', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('offensive_flag_count', self.gf('django.db.models.fields.SmallIntegerField')(default=0)),\r
+            ('closed_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),\r
+            ('deleted_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('last_activity_by', self.gf('django.db.models.fields.related.ForeignKey')(related_name='last_active_in_questions', to=orm['forum.User'])),\r
+            ('view_count', self.gf('django.db.models.fields.IntegerField')(default=0)),\r
+            ('locked_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),\r
+            ('score', self.gf('django.db.models.fields.IntegerField')(default=0)),\r
+            ('author', self.gf('django.db.models.fields.related.ForeignKey')(related_name='questions', to=orm['forum.User'])),\r
+            ('comment_count', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),\r
+            ('html', self.gf('django.db.models.fields.TextField')()),\r
+            ('vote_down_count', self.gf('django.db.models.fields.IntegerField')(default=0)),\r
+            ('closed', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('last_edited_by', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='last_edited_questions', null=True, to=orm['forum.User'])),\r
+            ('favourite_count', self.gf('django.db.models.fields.IntegerField')(default=0)),\r
+            ('deleted', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('summary', self.gf('django.db.models.fields.CharField')(max_length=180)),\r
+            ('answer_count', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),\r
+            ('last_activity_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+            ('closed_by', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='closed_questions', null=True, to=orm['forum.User'])),\r
+            ('close_reason', self.gf('django.db.models.fields.SmallIntegerField')(null=True, blank=True)),\r
+            ('locked', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('tagnames', self.gf('django.db.models.fields.CharField')(max_length=125)),\r
+            ('locked_by', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='locked_questions', null=True, to=orm['forum.User'])),\r
+            ('added_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+            ('deleted_by', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='deleted_questions', null=True, to=orm['forum.User'])),\r
+            ('wikified_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),\r
+            ('title', self.gf('django.db.models.fields.CharField')(max_length=300)),\r
+            ('last_edited_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),\r
+        ))\r
+        db.send_create_signal('forum', ['Question'])\r
+\r
+        # Adding M2M table for field followed_by on 'Question'\r
+        db.create_table(u'question_followed_by', (\r
+            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),\r
+            ('question', models.ForeignKey(orm['forum.question'], null=False)),\r
+            ('user', models.ForeignKey(orm['forum.user'], null=False))\r
+        ))\r
+        db.create_unique(u'question_followed_by', ['question_id', 'user_id'])\r
+\r
+        # Adding M2M table for field tags on 'Question'\r
+        db.create_table(u'question_tags', (\r
+            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),\r
+            ('question', models.ForeignKey(orm['forum.question'], null=False)),\r
+            ('tag', models.ForeignKey(orm['forum.tag'], null=False))\r
+        ))\r
+        db.create_unique(u'question_tags', ['question_id', 'tag_id'])\r
+\r
+        # Adding model 'QuestionSubscription'\r
+        db.create_table('forum_questionsubscription', (\r
+            ('last_view', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime(2010, 4, 6, 10, 36, 23, 725000))),\r
+            ('auto_subscription', self.gf('django.db.models.fields.BooleanField')(default=True, blank=True)),\r
+            ('question', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.Question'])),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.User'])),\r
+        ))\r
+        db.send_create_signal('forum', ['QuestionSubscription'])\r
+\r
+        # Adding model 'FavoriteQuestion'\r
+        db.create_table(u'favorite_question', (\r
+            ('question', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.Question'])),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('added_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+            ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='user_favorite_questions', to=orm['forum.User'])),\r
+        ))\r
+        db.send_create_signal('forum', ['FavoriteQuestion'])\r
+\r
+        # Adding model 'QuestionRevision'\r
+        db.create_table(u'question_revision', (\r
+            ('author', self.gf('django.db.models.fields.related.ForeignKey')(related_name='questionrevisions', to=orm['forum.User'])),\r
+            ('tagnames', self.gf('django.db.models.fields.CharField')(max_length=125)),\r
+            ('text', self.gf('django.db.models.fields.TextField')()),\r
+            ('title', self.gf('django.db.models.fields.CharField')(max_length=300)),\r
+            ('question', self.gf('django.db.models.fields.related.ForeignKey')(related_name='revisions', to=orm['forum.Question'])),\r
+            ('revised_at', self.gf('django.db.models.fields.DateTimeField')()),\r
+            ('summary', self.gf('django.db.models.fields.CharField')(max_length=300, blank=True)),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('revision', self.gf('django.db.models.fields.PositiveIntegerField')()),\r
+        ))\r
+        db.send_create_signal('forum', ['QuestionRevision'])\r
+\r
+        # Adding model 'AnonymousQuestion'\r
+        db.create_table('forum_anonymousquestion', (\r
+            ('wiki', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('ip_addr', self.gf('django.db.models.fields.IPAddressField')(max_length=15)),\r
+            ('author', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.User'], null=True)),\r
+            ('tagnames', self.gf('django.db.models.fields.CharField')(max_length=125)),\r
+            ('text', self.gf('django.db.models.fields.TextField')()),\r
+            ('title', self.gf('django.db.models.fields.CharField')(max_length=300)),\r
+            ('added_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+            ('summary', self.gf('django.db.models.fields.CharField')(max_length=180)),\r
+            ('session_key', self.gf('django.db.models.fields.CharField')(max_length=40)),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+        ))\r
+        db.send_create_signal('forum', ['AnonymousQuestion'])\r
+\r
+        # Adding model 'Answer'\r
+        db.create_table(u'answer', (\r
+            ('wiki', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('vote_up_count', self.gf('django.db.models.fields.IntegerField')(default=0)),\r
+            ('offensive_flag_count', self.gf('django.db.models.fields.SmallIntegerField')(default=0)),\r
+            ('deleted_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('locked_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),\r
+            ('score', self.gf('django.db.models.fields.IntegerField')(default=0)),\r
+            ('author', self.gf('django.db.models.fields.related.ForeignKey')(related_name='answers', to=orm['forum.User'])),\r
+            ('question', self.gf('django.db.models.fields.related.ForeignKey')(related_name='answers', to=orm['forum.Question'])),\r
+            ('comment_count', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),\r
+            ('html', self.gf('django.db.models.fields.TextField')()),\r
+            ('vote_down_count', self.gf('django.db.models.fields.IntegerField')(default=0)),\r
+            ('last_edited_by', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='last_edited_answers', null=True, to=orm['forum.User'])),\r
+            ('accepted_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),\r
+            ('deleted', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('accepted', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('locked', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('locked_by', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='locked_answers', null=True, to=orm['forum.User'])),\r
+            ('added_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+            ('deleted_by', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='deleted_answers', null=True, to=orm['forum.User'])),\r
+            ('wikified_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),\r
+            ('last_edited_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),\r
+        ))\r
+        db.send_create_signal('forum', ['Answer'])\r
+\r
+        # Adding model 'AnswerRevision'\r
+        db.create_table(u'answer_revision', (\r
+            ('author', self.gf('django.db.models.fields.related.ForeignKey')(related_name='answerrevisions', to=orm['forum.User'])),\r
+            ('text', self.gf('django.db.models.fields.TextField')()),\r
+            ('revised_at', self.gf('django.db.models.fields.DateTimeField')()),\r
+            ('summary', self.gf('django.db.models.fields.CharField')(max_length=300, blank=True)),\r
+            ('answer', self.gf('django.db.models.fields.related.ForeignKey')(related_name='revisions', to=orm['forum.Answer'])),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('revision', self.gf('django.db.models.fields.PositiveIntegerField')()),\r
+        ))\r
+        db.send_create_signal('forum', ['AnswerRevision'])\r
+\r
+        # Adding model 'AnonymousAnswer'\r
+        db.create_table('forum_anonymousanswer', (\r
+            ('wiki', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('ip_addr', self.gf('django.db.models.fields.IPAddressField')(max_length=15)),\r
+            ('author', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.User'], null=True)),\r
+            ('text', self.gf('django.db.models.fields.TextField')()),\r
+            ('question', self.gf('django.db.models.fields.related.ForeignKey')(related_name='anonymous_answers', to=orm['forum.Question'])),\r
+            ('added_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+            ('summary', self.gf('django.db.models.fields.CharField')(max_length=180)),\r
+            ('session_key', self.gf('django.db.models.fields.CharField')(max_length=40)),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+        ))\r
+        db.send_create_signal('forum', ['AnonymousAnswer'])\r
+\r
+        # Adding model 'Badge'\r
+        db.create_table(u'badge', (\r
+            ('multiple', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('description', self.gf('django.db.models.fields.CharField')(max_length=300)),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('awarded_count', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),\r
+            ('type', self.gf('django.db.models.fields.SmallIntegerField')()),\r
+            ('slug', self.gf('django.db.models.fields.SlugField')(db_index=True, max_length=50, blank=True)),\r
+            ('name', self.gf('django.db.models.fields.CharField')(max_length=50)),\r
+        ))\r
+        db.send_create_signal('forum', ['Badge'])\r
+\r
+        # Adding unique constraint on 'Badge', fields ['name', 'type']\r
+        db.create_unique(u'badge', ['name', 'type'])\r
+\r
+        # Adding model 'Award'\r
+        db.create_table(u'award', (\r
+            ('awarded_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+            ('notified', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('object_id', self.gf('django.db.models.fields.PositiveIntegerField')()),\r
+            ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='awards', to=orm['forum.User'])),\r
+            ('content_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['contenttypes.ContentType'])),\r
+            ('badge', self.gf('django.db.models.fields.related.ForeignKey')(related_name='award_badge', to=orm['forum.Badge'])),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+        ))\r
+        db.send_create_signal('forum', ['Award'])\r
+\r
+        # Adding unique constraint on 'Award', fields ['content_type', 'object_id', 'user', 'badge']\r
+        db.create_unique(u'award', ['content_type_id', 'object_id', 'user_id', 'badge_id'])\r
+\r
+        # Adding model 'Repute'\r
+        db.create_table(u'repute', (\r
+            ('positive', self.gf('django.db.models.fields.SmallIntegerField')(default=0)),\r
+            ('question', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.Question'])),\r
+            ('negative', self.gf('django.db.models.fields.SmallIntegerField')(default=0)),\r
+            ('reputation_type', self.gf('django.db.models.fields.SmallIntegerField')()),\r
+            ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.User'])),\r
+            ('reputed_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('reputation', self.gf('django.db.models.fields.IntegerField')(default=1)),\r
+        ))\r
+        db.send_create_signal('forum', ['Repute'])\r
+\r
+        # Adding model 'KeyValue'\r
+        db.create_table('forum_keyvalue', (\r
+            ('value', self.gf('forum.models.utils.PickledObjectField')()),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('key', self.gf('django.db.models.fields.CharField')(unique=True, max_length=255)),\r
+        ))\r
+        db.send_create_signal('forum', ['KeyValue'])\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        \r
+        # Deleting model 'User'\r
+        db.delete_table('forum_user')\r
+\r
+        # Deleting model 'Activity'\r
+        db.delete_table(u'activity')\r
+\r
+        # Deleting model 'SubscriptionSettings'\r
+        db.delete_table('forum_subscriptionsettings')\r
+\r
+        # Deleting model 'ValidationHash'\r
+        db.delete_table('forum_validationhash')\r
+\r
+        # Removing unique constraint on 'ValidationHash', fields ['user', 'type']\r
+        db.delete_unique('forum_validationhash', ['user_id', 'type'])\r
+\r
+        # Deleting model 'AuthKeyUserAssociation'\r
+        db.delete_table('forum_authkeyuserassociation')\r
+\r
+        # Deleting model 'Vote'\r
+        db.delete_table(u'vote')\r
+\r
+        # Removing unique constraint on 'Vote', fields ['content_type', 'object_id', 'user']\r
+        db.delete_unique(u'vote', ['content_type_id', 'object_id', 'user_id'])\r
+\r
+        # Deleting model 'FlaggedItem'\r
+        db.delete_table(u'flagged_item')\r
+\r
+        # Removing unique constraint on 'FlaggedItem', fields ['content_type', 'object_id', 'user']\r
+        db.delete_unique(u'flagged_item', ['content_type_id', 'object_id', 'user_id'])\r
+\r
+        # Deleting model 'Comment'\r
+        db.delete_table(u'comment')\r
+\r
+        # Deleting model 'Tag'\r
+        db.delete_table(u'tag')\r
+\r
+        # Deleting model 'MarkedTag'\r
+        db.delete_table('forum_markedtag')\r
+\r
+        # Deleting model 'Question'\r
+        db.delete_table(u'question')\r
+\r
+        # Removing M2M table for field followed_by on 'Question'\r
+        db.delete_table('question_followed_by')\r
+\r
+        # Removing M2M table for field tags on 'Question'\r
+        db.delete_table('question_tags')\r
+\r
+        # Deleting model 'QuestionSubscription'\r
+        db.delete_table('forum_questionsubscription')\r
+\r
+        # Deleting model 'FavoriteQuestion'\r
+        db.delete_table(u'favorite_question')\r
+\r
+        # Deleting model 'QuestionRevision'\r
+        db.delete_table(u'question_revision')\r
+\r
+        # Deleting model 'AnonymousQuestion'\r
+        db.delete_table('forum_anonymousquestion')\r
+\r
+        # Deleting model 'Answer'\r
+        db.delete_table(u'answer')\r
+\r
+        # Deleting model 'AnswerRevision'\r
+        db.delete_table(u'answer_revision')\r
+\r
+        # Deleting model 'AnonymousAnswer'\r
+        db.delete_table('forum_anonymousanswer')\r
+\r
+        # Deleting model 'Badge'\r
+        db.delete_table(u'badge')\r
+\r
+        # Removing unique constraint on 'Badge', fields ['name', 'type']\r
+        db.delete_unique(u'badge', ['name', 'type'])\r
+\r
+        # Deleting model 'Award'\r
+        db.delete_table(u'award')\r
+\r
+        # Removing unique constraint on 'Award', fields ['content_type', 'object_id', 'user', 'badge']\r
+        db.delete_unique(u'award', ['content_type_id', 'object_id', 'user_id', 'badge_id'])\r
+\r
+        # Deleting model 'Repute'\r
+        db.delete_table(u'repute')\r
+\r
+        # Deleting model 'KeyValue'\r
+        db.delete_table('forum_keyvalue')\r
+    \r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.anonymousanswer': {\r
+            'Meta': {'object_name': 'AnonymousAnswer'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_answers'", 'to': "orm['forum.Question']"}),\r
+            'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.anonymousquestion': {\r
+            'Meta': {'object_name': 'AnonymousQuestion'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),\r
+            'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.answer': {\r
+            'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"},\r
+            'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['forum.User']"}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_answers'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'html': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_answers'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'locked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'locked_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'locked_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locked_answers'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['forum.Question']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.answerrevision': {\r
+            'Meta': {'object_name': 'AnswerRevision', 'db_table': "u'answer_revision'"},\r
+            'answer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Answer']"}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answerrevisions'", 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}),\r
+            'text': ('django.db.models.fields.TextField', [], {})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('content_type', 'object_id', 'user', 'badge'),)", 'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.comment': {\r
+            'Meta': {'object_name': 'Comment', 'db_table': "u'comment'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'comment': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.favoritequestion': {\r
+            'Meta': {'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.flaggeditem': {\r
+            'Meta': {'unique_together': "(('content_type', 'object_id', 'user'),)", 'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"},\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.question': {\r
+            'Meta': {'object_name': 'Question', 'db_table': "u'question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'answer_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questions'", 'to': "orm['forum.User']"}),\r
+            'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['forum.User']"}),\r
+            'favourite_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'followed_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'followed_questions'", 'to': "orm['forum.User']"}),\r
+            'html': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'to': "orm['forum.User']"}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'locked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'locked_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'locked_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locked_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'subscribers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscriptions'", 'through': "'QuestionSubscription'", 'to': "orm['forum.User']"}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'questions'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'view_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.questionrevision': {\r
+            'Meta': {'object_name': 'QuestionRevision', 'db_table': "u'question_revision'"},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questionrevisions'", 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Question']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 6, 10, 36, 23, 725000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.repute': {\r
+            'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'negative': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'positive': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'reputation': ('django.db.models.fields.IntegerField', [], {'default': '1'}),\r
+            'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'gravatar': ('django.db.models.fields.CharField', [], {'max_length': '32'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'tag_filter_setting': ('django.db.models.fields.CharField', [], {'default': "'ignored'", 'max_length': '16'}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 7, 10, 36, 23, 863000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'unique_together': "(('content_type', 'object_id', 'user'),)", 'object_name': 'Vote', 'db_table': "u'vote'"},\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'vote': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0002_auto__add_likedcomment__del_field_repute_positive__del_field_repute_ne.py b/forum/modules/template_loader.py/forum/migrations/0002_auto__add_likedcomment__del_field_repute_positive__del_field_repute_ne.py
new file mode 100644 (file)
index 0000000..36ff8e2
--- /dev/null
@@ -0,0 +1,481 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import SchemaMigration\r
+from django.db import models\r
+\r
+class Migration(SchemaMigration):\r
+    \r
+    def forwards(self, orm):\r
+        \r
+        # Adding model 'LikedComment'\r
+        db.create_table('forum_likedcomment', (\r
+            ('comment', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.Comment'])),\r
+            ('canceled', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('added_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+            ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.User'])),\r
+        ))\r
+        db.send_create_signal('forum', ['LikedComment'])\r
+\r
+        # Adding field 'Repute.value'\r
+        db.add_column(u'repute', 'value', self.gf('django.db.models.fields.SmallIntegerField')(default=0), keep_default=False)\r
+\r
+        # Adding field 'Repute.user_previous_rep'\r
+        db.add_column(u'repute', 'user_previous_rep', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)\r
+\r
+        # Adding field 'Vote.canceled'\r
+        db.add_column(u'vote', 'canceled', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True), keep_default=False)\r
+\r
+        # Removing unique constraint on 'Vote', fields ['object_id', 'content_type', 'user']\r
+        db.delete_unique(u'vote', ['object_id', 'content_type_id', 'user_id'])\r
+\r
+        # Adding field 'Comment.deleted'\r
+        db.add_column(u'comment', 'deleted', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True), keep_default=False)\r
+\r
+        # Adding field 'Comment.deleted_by'\r
+        db.add_column(u'comment', 'deleted_by', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='deleted_comments', null=True, to=orm['forum.User']), keep_default=False)\r
+\r
+        # Adding field 'Comment.score'\r
+        db.add_column(u'comment', 'score', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)\r
+\r
+        # Adding field 'Comment.deleted_at'\r
+        db.add_column(u'comment', 'deleted_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True), keep_default=False)\r
+\r
+        # Deleting field 'Answer.locked_at'\r
+        db.delete_column(u'answer', 'locked_at')\r
+\r
+        # Deleting field 'Answer.locked'\r
+        db.delete_column(u'answer', 'locked')\r
+\r
+        # Deleting field 'Answer.locked_by'\r
+        db.delete_column(u'answer', 'locked_by_id')\r
+\r
+        # Adding field 'Answer.accepted_by'\r
+        db.add_column(u'answer', 'accepted_by', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.User'], null=True), keep_default=False)\r
+\r
+        # Adding field 'FlaggedItem.canceled'\r
+        db.add_column(u'flagged_item', 'canceled', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True), keep_default=False)\r
+\r
+        # Adding field 'FlaggedItem.reason'\r
+        db.add_column(u'flagged_item', 'reason', self.gf('django.db.models.fields.CharField')(max_length=300, null=True), keep_default=False)\r
+\r
+        # Removing unique constraint on 'FlaggedItem', fields ['object_id', 'content_type', 'user']\r
+        db.delete_unique(u'flagged_item', ['object_id', 'content_type_id', 'user_id'])\r
+\r
+        # Adding unique constraint on 'FavoriteQuestion', fields ['question', 'user']\r
+        db.create_unique(u'favorite_question', ['question_id', 'user_id'])\r
+\r
+        # Deleting field 'User.gravatar'\r
+        db.delete_column('forum_user', 'gravatar')\r
+\r
+        # Deleting field 'User.tag_filter_setting'\r
+        db.delete_column('forum_user', 'tag_filter_setting')\r
+\r
+        # Deleting field 'Question.locked_at'\r
+        db.delete_column(u'question', 'locked_at')\r
+\r
+        # Deleting field 'Question.locked'\r
+        db.delete_column(u'question', 'locked')\r
+\r
+        # Deleting field 'Question.locked_by'\r
+        db.delete_column(u'question', 'locked_by_id')\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        \r
+        # Deleting model 'LikedComment'\r
+        db.delete_table('forum_likedcomment')\r
+\r
+        # Deleting field 'Repute.value'\r
+        db.delete_column(u'repute', 'value')\r
+\r
+        # Deleting field 'Repute.user_previous_rep'\r
+        db.delete_column(u'repute', 'user_previous_rep')\r
+\r
+        # Deleting field 'Vote.canceled'\r
+        db.delete_column(u'vote', 'canceled')\r
+\r
+        # Adding unique constraint on 'Vote', fields ['object_id', 'content_type', 'user']\r
+        db.create_unique(u'vote', ['object_id', 'content_type_id', 'user_id'])\r
+\r
+        # Deleting field 'Comment.deleted'\r
+        db.delete_column(u'comment', 'deleted')\r
+\r
+        # Deleting field 'Comment.deleted_by'\r
+        db.delete_column(u'comment', 'deleted_by_id')\r
+\r
+        # Deleting field 'Comment.score'\r
+        db.delete_column(u'comment', 'score')\r
+\r
+        # Deleting field 'Comment.deleted_at'\r
+        db.delete_column(u'comment', 'deleted_at')\r
+\r
+        # Adding field 'Answer.locked_at'\r
+        db.add_column(u'answer', 'locked_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True), keep_default=False)\r
+\r
+        # Adding field 'Answer.locked'\r
+        db.add_column(u'answer', 'locked', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True), keep_default=False)\r
+\r
+        # Adding field 'Answer.locked_by'\r
+        db.add_column(u'answer', 'locked_by', self.gf('django.db.models.fields.related.ForeignKey')(related_name='locked_answers', null=True, to=orm['forum.User'], blank=True), keep_default=False)\r
+\r
+        # Deleting field 'Answer.accepted_by'\r
+        db.delete_column(u'answer', 'accepted_by_id')\r
+\r
+        # Deleting field 'FlaggedItem.canceled'\r
+        db.delete_column(u'flagged_item', 'canceled')\r
+\r
+        # Deleting field 'FlaggedItem.reason'\r
+        db.delete_column(u'flagged_item', 'reason')\r
+\r
+        # Adding unique constraint on 'FlaggedItem', fields ['object_id', 'content_type', 'user']\r
+        db.create_unique(u'flagged_item', ['object_id', 'content_type_id', 'user_id'])\r
+\r
+        # Removing unique constraint on 'FavoriteQuestion', fields ['question', 'user']\r
+        db.delete_unique(u'favorite_question', ['question_id', 'user_id'])\r
+\r
+        # Adding field 'User.gravatar'\r
+        db.add_column('forum_user', 'gravatar', self.gf('django.db.models.fields.CharField')(default='', max_length=32), keep_default=False)\r
+\r
+        # Adding field 'User.tag_filter_setting'\r
+        db.add_column('forum_user', 'tag_filter_setting', self.gf('django.db.models.fields.CharField')(default='ignored', max_length=16), keep_default=False)\r
+\r
+        # Adding field 'Question.locked_at'\r
+        db.add_column(u'question', 'locked_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True), keep_default=False)\r
+\r
+        # Adding field 'Question.locked'\r
+        db.add_column(u'question', 'locked', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True), keep_default=False)\r
+\r
+        # Adding field 'Question.locked_by'\r
+        db.add_column(u'question', 'locked_by', self.gf('django.db.models.fields.related.ForeignKey')(related_name='locked_questions', null=True, to=orm['forum.User'], blank=True), keep_default=False)\r
+    \r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.anonymousanswer': {\r
+            'Meta': {'object_name': 'AnonymousAnswer'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_answers'", 'to': "orm['forum.Question']"}),\r
+            'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.anonymousquestion': {\r
+            'Meta': {'object_name': 'AnonymousQuestion'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),\r
+            'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.answer': {\r
+            'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"},\r
+            'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'accepted_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['forum.User']"}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_answers'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'html': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_answers'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['forum.Question']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.answerrevision': {\r
+            'Meta': {'object_name': 'AnswerRevision', 'db_table': "u'answer_revision'"},\r
+            'answer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Answer']"}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answerrevisions'", 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}),\r
+            'text': ('django.db.models.fields.TextField', [], {})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('content_type', 'object_id', 'user', 'badge'),)", 'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.comment': {\r
+            'Meta': {'object_name': 'Comment', 'db_table': "u'comment'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'comment': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_comments'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'liked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'comments_liked'", 'through': "'LikedComment'", 'to': "orm['forum.User']"}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.favoritequestion': {\r
+            'Meta': {'unique_together': "(('question', 'user'),)", 'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.flaggeditem': {\r
+            'Meta': {'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.likedcomment': {\r
+            'Meta': {'object_name': 'LikedComment'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'comment': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Comment']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.question': {\r
+            'Meta': {'object_name': 'Question', 'db_table': "u'question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'answer_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questions'", 'to': "orm['forum.User']"}),\r
+            'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['forum.User']"}),\r
+            'favourite_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'followed_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'followed_questions'", 'to': "orm['forum.User']"}),\r
+            'html': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'to': "orm['forum.User']"}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'subscribers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscriptions'", 'through': "'QuestionSubscription'", 'to': "orm['forum.User']"}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'questions'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'view_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.questionrevision': {\r
+            'Meta': {'object_name': 'QuestionRevision', 'db_table': "u'question_revision'"},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questionrevisions'", 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Question']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 6, 11, 11, 44, 616000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.repute': {\r
+            'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+                       'negative': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'positive': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'reputation': ('django.db.models.fields.IntegerField', [], {'default': '1'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'user_previous_rep': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 7, 11, 11, 52, 402000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'object_name': 'Vote', 'db_table': "u'vote'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'vote': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0003_repute_changes.py b/forum/modules/template_loader.py/forum/migrations/0003_repute_changes.py
new file mode 100644 (file)
index 0000000..cdcbd22
--- /dev/null
@@ -0,0 +1,355 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import DataMigration\r
+from django.db import models\r
+\r
+class Migration(DataMigration):\r
+    \r
+    def forwards(self, orm):\r
+        for r in orm.Repute.objects.all():\r
+            r.value = r.positive + r.negative\r
+            r.user_previous_rep = r.reputation - r.value\r
+            r.save()\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        for r in orm.Repute.objects.all():\r
+            if r.value > 0:\r
+                r.positive = r.value\r
+                r.negative = 0\r
+            else:\r
+                r.positive = 0\r
+                r.negative = r.value\r
+\r
+            r.reputation = r.user_previous_rep + r.value\r
+            r.save()\r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.anonymousanswer': {\r
+            'Meta': {'object_name': 'AnonymousAnswer'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_answers'", 'to': "orm['forum.Question']"}),\r
+            'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.anonymousquestion': {\r
+            'Meta': {'object_name': 'AnonymousQuestion'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),\r
+            'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.answer': {\r
+            'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"},\r
+            'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'accepted_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['forum.User']"}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_answers'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'html': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_answers'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['forum.Question']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.answerrevision': {\r
+            'Meta': {'object_name': 'AnswerRevision', 'db_table': "u'answer_revision'"},\r
+            'answer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Answer']"}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answerrevisions'", 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}),\r
+            'text': ('django.db.models.fields.TextField', [], {})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('content_type', 'object_id', 'user', 'badge'),)", 'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.comment': {\r
+            'Meta': {'object_name': 'Comment', 'db_table': "u'comment'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'comment': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_comments'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'liked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'comments_liked'", 'through': "'LikedComment'", 'to': "orm['forum.User']"}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.favoritequestion': {\r
+            'Meta': {'unique_together': "(('question', 'user'),)", 'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.flaggeditem': {\r
+            'Meta': {'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.likedcomment': {\r
+            'Meta': {'object_name': 'LikedComment'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'comment': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Comment']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.question': {\r
+            'Meta': {'object_name': 'Question', 'db_table': "u'question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'answer_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questions'", 'to': "orm['forum.User']"}),\r
+            'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['forum.User']"}),\r
+            'favourite_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'followed_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'followed_questions'", 'to': "orm['forum.User']"}),\r
+            'html': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'to': "orm['forum.User']"}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'subscribers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscriptions'", 'through': "'QuestionSubscription'", 'to': "orm['forum.User']"}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'questions'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'view_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.questionrevision': {\r
+            'Meta': {'object_name': 'QuestionRevision', 'db_table': "u'question_revision'"},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questionrevisions'", 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Question']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 6, 11, 30, 3, 497000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.repute': {\r
+            'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'negative': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'positive': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'reputation': ('django.db.models.fields.IntegerField', [], {'default': '1'}),\r
+            'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'user_previous_rep': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 7, 11, 30, 3, 573000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'object_name': 'Vote', 'db_table': "u'vote'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'vote': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0004_auto__del_field_repute_negative__del_field_repute_positive__del_field_.py b/forum/modules/template_loader.py/forum/migrations/0004_auto__del_field_repute_negative__del_field_repute_positive__del_field_.py
new file mode 100644 (file)
index 0000000..5faa7b0
--- /dev/null
@@ -0,0 +1,357 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import SchemaMigration\r
+from django.db import models\r
+\r
+class Migration(SchemaMigration):\r
+    \r
+    def forwards(self, orm):\r
+        \r
+        # Deleting field 'Repute.negative'\r
+        db.delete_column(u'repute', 'negative')\r
+\r
+        # Deleting field 'Repute.positive'\r
+        db.delete_column(u'repute', 'positive')\r
+\r
+        # Deleting field 'Repute.reputation'\r
+        db.delete_column(u'repute', 'reputation')\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        \r
+        # Adding field 'Repute.negative'\r
+        db.add_column(u'repute', 'negative', self.gf('django.db.models.fields.SmallIntegerField')(default=0), keep_default=False)\r
+\r
+        # Adding field 'Repute.positive'\r
+        db.add_column(u'repute', 'positive', self.gf('django.db.models.fields.SmallIntegerField')(default=0), keep_default=False)\r
+\r
+        # Adding field 'Repute.reputation'\r
+        db.add_column(u'repute', 'reputation', self.gf('django.db.models.fields.IntegerField')(default=1), keep_default=False)\r
+    \r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.anonymousanswer': {\r
+            'Meta': {'object_name': 'AnonymousAnswer'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_answers'", 'to': "orm['forum.Question']"}),\r
+            'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.anonymousquestion': {\r
+            'Meta': {'object_name': 'AnonymousQuestion'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),\r
+            'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.answer': {\r
+            'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"},\r
+            'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'accepted_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['forum.User']"}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_answers'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'html': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_answers'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['forum.Question']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.answerrevision': {\r
+            'Meta': {'object_name': 'AnswerRevision', 'db_table': "u'answer_revision'"},\r
+            'answer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Answer']"}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answerrevisions'", 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}),\r
+            'text': ('django.db.models.fields.TextField', [], {})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('content_type', 'object_id', 'user', 'badge'),)", 'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.comment': {\r
+            'Meta': {'object_name': 'Comment', 'db_table': "u'comment'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'comment': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_comments'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'liked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'comments_liked'", 'through': "'LikedComment'", 'to': "orm['forum.User']"}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.favoritequestion': {\r
+            'Meta': {'unique_together': "(('question', 'user'),)", 'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.flaggeditem': {\r
+            'Meta': {'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.likedcomment': {\r
+            'Meta': {'object_name': 'LikedComment'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'comment': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Comment']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.question': {\r
+            'Meta': {'object_name': 'Question', 'db_table': "u'question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'answer_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questions'", 'to': "orm['forum.User']"}),\r
+            'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['forum.User']"}),\r
+            'favourite_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'followed_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'followed_questions'", 'to': "orm['forum.User']"}),\r
+            'html': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'to': "orm['forum.User']"}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'subscribers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscriptions'", 'through': "'QuestionSubscription'", 'to': "orm['forum.User']"}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'questions'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'view_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.questionrevision': {\r
+            'Meta': {'object_name': 'QuestionRevision', 'db_table': "u'question_revision'"},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questionrevisions'", 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Question']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 6, 11, 40, 26, 816000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.repute': {\r
+            'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'user_previous_rep': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 7, 11, 40, 27, 72000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'object_name': 'Vote', 'db_table': "u'vote'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'vote': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0005_fill_accepted_by_field.py b/forum/modules/template_loader.py/forum/migrations/0005_fill_accepted_by_field.py
new file mode 100644 (file)
index 0000000..cc7d0b0
--- /dev/null
@@ -0,0 +1,341 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import DataMigration\r
+from django.db import models\r
+\r
+class Migration(DataMigration):\r
+    \r
+    def forwards(self, orm):\r
+        for a in orm.Answer.objects.filter(accepted=True):\r
+            a.accepted_by = a.question.author\r
+            a.save()\r
+    \r
+    def backwards(self, orm):\r
+        "Write your backwards methods here."\r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.anonymousanswer': {\r
+            'Meta': {'object_name': 'AnonymousAnswer'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_answers'", 'to': "orm['forum.Question']"}),\r
+            'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.anonymousquestion': {\r
+            'Meta': {'object_name': 'AnonymousQuestion'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),\r
+            'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.answer': {\r
+            'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"},\r
+            'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'accepted_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['forum.User']"}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_answers'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'html': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_answers'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['forum.Question']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.answerrevision': {\r
+            'Meta': {'object_name': 'AnswerRevision', 'db_table': "u'answer_revision'"},\r
+            'answer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Answer']"}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answerrevisions'", 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}),\r
+            'text': ('django.db.models.fields.TextField', [], {})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('content_type', 'object_id', 'user', 'badge'),)", 'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.comment': {\r
+            'Meta': {'object_name': 'Comment', 'db_table': "u'comment'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'comment': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_comments'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'liked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'comments_liked'", 'through': "'LikedComment'", 'to': "orm['forum.User']"}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.favoritequestion': {\r
+            'Meta': {'unique_together': "(('question', 'user'),)", 'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.flaggeditem': {\r
+            'Meta': {'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.likedcomment': {\r
+            'Meta': {'object_name': 'LikedComment'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'comment': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Comment']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.question': {\r
+            'Meta': {'object_name': 'Question', 'db_table': "u'question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'answer_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questions'", 'to': "orm['forum.User']"}),\r
+            'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['forum.User']"}),\r
+            'favourite_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'followed_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'followed_questions'", 'to': "orm['forum.User']"}),\r
+            'html': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'to': "orm['forum.User']"}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'subscribers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscriptions'", 'through': "'QuestionSubscription'", 'to': "orm['forum.User']"}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'questions'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'view_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.questionrevision': {\r
+            'Meta': {'object_name': 'QuestionRevision', 'db_table': "u'question_revision'"},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questionrevisions'", 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Question']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 6, 11, 46, 14, 452000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.repute': {\r
+            'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'user_previous_rep': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 7, 11, 46, 14, 538000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'object_name': 'Vote', 'db_table': "u'vote'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'vote': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0006_auto__add_node__add_field_vote_node__add_field_comment_node__add_field.py b/forum/modules/template_loader.py/forum/migrations/0006_auto__add_node__add_field_vote_node__add_field_comment_node__add_field.py
new file mode 100644 (file)
index 0000000..bee4368
--- /dev/null
@@ -0,0 +1,433 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import SchemaMigration\r
+from django.db import models\r
+\r
+class Migration(SchemaMigration):\r
+    \r
+    def forwards(self, orm):\r
+        \r
+        # Adding model 'Node'\r
+        db.create_table('forum_node', (\r
+            ('body', self.gf('django.db.models.fields.TextField')()),\r
+            ('vote_up_count', self.gf('django.db.models.fields.IntegerField')(default=0)),\r
+            ('parent', self.gf('django.db.models.fields.related.ForeignKey')(related_name='childs', null=True, to=orm['forum.Node'])),\r
+            ('author', self.gf('django.db.models.fields.related.ForeignKey')(related_name='nodes', to=orm['forum.User'])),\r
+            ('deleted', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('title', self.gf('django.db.models.fields.CharField')(max_length=300)),\r
+            ('comment_count', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),\r
+            ('added_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+            ('deleted_by', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='deleted_nodes', null=True, to=orm['forum.User'])),\r
+            ('tagnames', self.gf('django.db.models.fields.CharField')(max_length=125)),\r
+            ('node_type', self.gf('django.db.models.fields.CharField')(default='node', max_length=16)),\r
+            ('score', self.gf('django.db.models.fields.IntegerField')(default=0)),\r
+            ('vote_down_count', self.gf('django.db.models.fields.IntegerField')(default=0)),\r
+            ('offensive_flag_count', self.gf('django.db.models.fields.SmallIntegerField')(default=0)),\r
+            ('last_edited_by', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='last_edited_nodes', null=True, to=orm['forum.User'])),\r
+            ('deleted_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('last_edited_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),\r
+        ))\r
+        db.send_create_signal('forum', ['Node'])\r
+\r
+        # Adding M2M table for field tags on 'Node'\r
+        db.create_table('forum_node_tags', (\r
+            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),\r
+            ('node', models.ForeignKey(orm['forum.node'], null=False)),\r
+            ('tag', models.ForeignKey(orm['forum.tag'], null=False))\r
+        ))\r
+        db.create_unique('forum_node_tags', ['node_id', 'tag_id'])\r
+\r
+        # Adding field 'Vote.node'\r
+        db.add_column(u'vote', 'node', self.gf('django.db.models.fields.related.ForeignKey')(related_name='votes', null=True, to=orm['forum.Node']), keep_default=False)\r
+\r
+        # Adding field 'Comment.node'\r
+        db.add_column(u'comment', 'node', self.gf('django.db.models.fields.related.ForeignKey')(related_name='comments', null=True, to=orm['forum.Node']), keep_default=False)\r
+\r
+        # Adding field 'Answer.node_ptr'\r
+        db.add_column(u'answer', 'node_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['forum.Node'], unique=True, null=True), keep_default=False)\r
+\r
+        # Adding field 'FlaggedItem.node'\r
+        db.add_column(u'flagged_item', 'node', self.gf('django.db.models.fields.related.ForeignKey')(related_name='flaggeditems', null=True, to=orm['forum.Node']), keep_default=False)\r
+\r
+        # Adding field 'Question.node_ptr'\r
+        db.add_column(u'question', 'node_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['forum.Node'], unique=True, null=True), keep_default=False)\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        \r
+        # Deleting model 'Node'\r
+        db.delete_table('forum_node')\r
+\r
+        # Removing M2M table for field tags on 'Node'\r
+        db.delete_table('forum_node_tags')\r
+\r
+        # Deleting field 'Vote.node'\r
+        db.delete_column(u'vote', 'node_id')\r
+\r
+        # Deleting field 'Comment.node'\r
+        db.delete_column(u'comment', 'node_id')\r
+\r
+        # Deleting field 'Answer.node_ptr'\r
+        db.delete_column(u'answer', 'node_ptr_id')\r
+\r
+        # Deleting field 'FlaggedItem.node'\r
+        db.delete_column(u'flagged_item', 'node_id')\r
+\r
+        # Deleting field 'Question.node_ptr'\r
+        db.delete_column(u'question', 'node_ptr_id')\r
+    \r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.anonymousanswer': {\r
+            'Meta': {'object_name': 'AnonymousAnswer'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_answers'", 'to': "orm['forum.Question']"}),\r
+            'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.anonymousquestion': {\r
+            'Meta': {'object_name': 'AnonymousQuestion'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),\r
+            'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.answer': {\r
+            'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"},\r
+            'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'accepted_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['forum.User']"}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_answers'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'html': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_answers'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'null': 'True'}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['forum.Question']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.answerrevision': {\r
+            'Meta': {'object_name': 'AnswerRevision', 'db_table': "u'answer_revision'"},\r
+            'answer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Answer']"}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answerrevisions'", 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}),\r
+            'text': ('django.db.models.fields.TextField', [], {})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('content_type', 'object_id', 'user', 'badge'),)", 'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.comment': {\r
+            'Meta': {'object_name': 'Comment', 'db_table': "u'comment'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'comment': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_comments'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'liked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'comments_liked'", 'through': "'LikedComment'", 'to': "orm['forum.User']"}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.favoritequestion': {\r
+            'Meta': {'unique_together': "(('question', 'user'),)", 'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.flaggeditem': {\r
+            'Meta': {'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.likedcomment': {\r
+            'Meta': {'object_name': 'LikedComment'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'comment': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Comment']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'childs'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.question': {\r
+            'Meta': {'object_name': 'Question', 'db_table': "u'question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'answer_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questions'", 'to': "orm['forum.User']"}),\r
+            'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['forum.User']"}),\r
+            'favourite_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'followed_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'followed_questions'", 'to': "orm['forum.User']"}),\r
+            'html': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'to': "orm['forum.User']"}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'null': 'True'}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'subscribers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscriptions'", 'through': "'QuestionSubscription'", 'to': "orm['forum.User']"}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'questions'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'view_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.questionrevision': {\r
+            'Meta': {'object_name': 'QuestionRevision', 'db_table': "u'question_revision'"},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questionrevisions'", 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Question']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 14, 1, 28, 41, 733000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.repute': {\r
+            'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'user_previous_rep': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 15, 1, 28, 41, 976000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'object_name': 'Vote', 'db_table': "u'vote'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'vote': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0007_q_and_a_to_node.py b/forum/modules/template_loader.py/forum/migrations/0007_q_and_a_to_node.py
new file mode 100644 (file)
index 0000000..0e283e0
--- /dev/null
@@ -0,0 +1,549 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import DataMigration\r
+from django.db import models\r
+from forum.migrations import ProgressBar\r
+\r
+class Migration(DataMigration):\r
+    \r
+    def forwards(self, orm):\r
+        #Converting questions\r
+        question_count = orm.Question.objects.all().count()\r
+        print "\nConverting %d questions:" % question_count\r
+        progress = ProgressBar(question_count)\r
+\r
+        question_id_map = {}\r
+\r
+        for q in orm.Question.objects.order_by('id'):\r
+            node = orm.Node(\r
+                node_type='question',\r
+                author=q.author,\r
+                added_at=q.added_at,\r
+                score=q.score,\r
+                vote_up_count=q.vote_up_count,\r
+                vote_down_count=q.vote_down_count,\r
+                offensive_flag_count=q.offensive_flag_count,\r
+                last_edited_at=q.last_edited_at,\r
+                last_edited_by=q.last_edited_by,\r
+                title=q.title,\r
+                body=q.html,\r
+                deleted=q.deleted,\r
+                deleted_by=q.deleted_by,\r
+                deleted_at=q.deleted_at,\r
+                tagnames=q.tagnames,\r
+                comment_count=q.comment_count,\r
+            )\r
+\r
+            node.save()\r
+            q.node_ptr = node\r
+            q.save()\r
+            node.tags = q.tags.all()\r
+\r
+            question_id_map[q.id] = node\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+\r
+        #Converting answers\r
+        answer_count = orm.Answer.objects.all().count()\r
+        print "Converting %d answers:" % answer_count\r
+        progress = ProgressBar(answer_count)\r
+\r
+        answer_id_map = {}\r
+\r
+        for a in orm.Answer.objects.order_by('id'):\r
+            node = orm.Node(\r
+                node_type='answer',\r
+                parent=question_id_map[a.question.id],\r
+                author=a.author,\r
+                added_at=a.added_at,\r
+                score=a.score,\r
+                vote_up_count=a.vote_up_count,\r
+                vote_down_count=a.vote_down_count,\r
+                offensive_flag_count=a.offensive_flag_count,\r
+                last_edited_at=a.last_edited_at,\r
+                last_edited_by=a.last_edited_by,\r
+                body=a.html,\r
+                deleted=a.deleted,\r
+                deleted_by=a.deleted_by,\r
+                deleted_at=a.deleted_at,\r
+                comment_count=a.comment_count,\r
+            )\r
+\r
+            node.save()\r
+            a.node_ptr = node\r
+            a.save()\r
+            answer_id_map[a.id] = node\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+\r
+        ctypes = dict([(ct.name, ct.id) for ct in orm['contenttypes.ContentType'].objects.all()])\r
+\r
+        #Converting votes\r
+        vote_count = orm.Vote.objects.all().count()\r
+        print "Converting %d vote references:" % vote_count\r
+        progress = ProgressBar(vote_count)\r
+        orfan_count = 0\r
+\r
+        for v in orm.Vote.objects.all():\r
+            node = (v.content_type.id == ctypes['question']) and question_id_map.get(v.object_id, None) \\r
+                                                             or answer_id_map.get(v.object_id, None)\r
+\r
+            if node:\r
+                v.node = node\r
+                v.save()\r
+            else:\r
+                v.delete()\r
+                orfan_count += 1\r
+\r
+            progress.update()\r
+\r
+        if orfan_count:\r
+            print "Deleted %d orfan votes"\r
+\r
+        print "\n...done\n"\r
+\r
+        #Converting flags\r
+        flag_count = orm.FlaggedItem.objects.all().count()\r
+        print "Converting %d flag references:" % flag_count\r
+        progress = ProgressBar(flag_count)\r
+        orfan_count = 0\r
+\r
+        for f in orm.FlaggedItem.objects.all():\r
+            node = (f.content_type.id == ctypes['question']) and question_id_map.get(f.object_id, None) \\r
+                                                             or answer_id_map.get(f.object_id, None)\r
+\r
+            if node:\r
+                f.node = node\r
+                f.save()\r
+            else:\r
+                f.delete()\r
+                orfan_count += 1\r
+\r
+            progress.update()\r
+\r
+        if orfan_count:\r
+            print "Deleted %d orfan votes"\r
+\r
+        print "\n...done\n"\r
+\r
+        #Converting comments\r
+        comment_count = orm.Comment.objects.all().count()\r
+        print "Converting %d comment references:" % comment_count\r
+        progress = ProgressBar(comment_count)\r
+        orfan_count = 0\r
+\r
+        for c in orm.Comment.objects.all():\r
+            node = (c.content_type.id == ctypes['question']) and question_id_map.get(c.object_id, None) \\r
+                                                             or answer_id_map.get(c.object_id, None)\r
+\r
+            if node:\r
+                c.node = node\r
+                c.save()\r
+            else:\r
+                c.delete()\r
+                orfan_count += 1\r
+\r
+            progress.update()\r
+\r
+        if orfan_count:\r
+            print "Deleted %d orfan comments"\r
+\r
+        print "\n...done\n"\r
+\r
+\r
+        #Converting awards\r
+        awards = orm.Award.objects.filter(content_type__id__in=(ctypes['question'], ctypes['answer']))\r
+        award_count = awards.count()\r
+        print "Converting %d award references:" % award_count\r
+        progress = ProgressBar(award_count)\r
+\r
+        for a in awards:\r
+            node = (a.content_type.id == ctypes['question']) and question_id_map.get(a.object_id, None) \\r
+                                                             or answer_id_map.get(a.object_id, None)\r
+\r
+            if node:\r
+                a.object_id = node.id\r
+                a.save()\r
+\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+\r
+\r
+        #Converting activity\r
+        activities = orm.Activity.objects.filter(content_type__id__in=(ctypes['question'], ctypes['answer']))\r
+        activity_count = activities.count()\r
+        print "Converting %d activity references:" % activity_count\r
+        progress = ProgressBar(activity_count)\r
+\r
+        for a in activities:\r
+            node = (a.content_type.id == ctypes['question']) and question_id_map.get(a.object_id, None) \\r
+                                                             or answer_id_map.get(a.object_id, None)\r
+\r
+            if node:\r
+                a.object_id = node.id\r
+                a.save()\r
+\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        "Write your backwards methods here."\r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.anonymousanswer': {\r
+            'Meta': {'object_name': 'AnonymousAnswer'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_answers'", 'to': "orm['forum.Question']"}),\r
+            'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.anonymousquestion': {\r
+            'Meta': {'object_name': 'AnonymousQuestion'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),\r
+            'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.answer': {\r
+            'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"},\r
+            'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'accepted_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['forum.User']"}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_answers'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'html': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_answers'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'null': 'True'}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['forum.Question']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.answerrevision': {\r
+            'Meta': {'object_name': 'AnswerRevision', 'db_table': "u'answer_revision'"},\r
+            'answer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Answer']"}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answerrevisions'", 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}),\r
+            'text': ('django.db.models.fields.TextField', [], {})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('content_type', 'object_id', 'user', 'badge'),)", 'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.comment': {\r
+            'Meta': {'object_name': 'Comment', 'db_table': "u'comment'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'comment': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_comments'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'liked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'comments_liked'", 'through': "'LikedComment'", 'to': "orm['forum.User']"}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.favoritequestion': {\r
+            'Meta': {'unique_together': "(('question', 'user'),)", 'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.flaggeditem': {\r
+            'Meta': {'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.likedcomment': {\r
+            'Meta': {'object_name': 'LikedComment'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'comment': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Comment']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'childs'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.question': {\r
+            'Meta': {'object_name': 'Question', 'db_table': "u'question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'answer_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questions'", 'to': "orm['forum.User']"}),\r
+            'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['forum.User']"}),\r
+            'favourite_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'followed_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'followed_questions'", 'to': "orm['forum.User']"}),\r
+            'html': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'to': "orm['forum.User']"}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'null': 'True'}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'subscribers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscriptions'", 'through': "'QuestionSubscription'", 'to': "orm['forum.User']"}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'questions'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'view_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.questionrevision': {\r
+            'Meta': {'object_name': 'QuestionRevision', 'db_table': "u'question_revision'"},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questionrevisions'", 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Question']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 14, 1, 29, 43, 727000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.repute': {\r
+            'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'user_previous_rep': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 15, 1, 29, 43, 815000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'object_name': 'Vote', 'db_table': "u'vote'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'vote': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0008_auto__add_noderevision__del_field_vote_object_id__del_field_vote_conte.py b/forum/modules/template_loader.py/forum/migrations/0008_auto__add_noderevision__del_field_vote_object_id__del_field_vote_conte.py
new file mode 100644 (file)
index 0000000..bb94406
--- /dev/null
@@ -0,0 +1,424 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import SchemaMigration\r
+from django.db import models\r
+\r
+class Migration(SchemaMigration):\r
+    \r
+    def forwards(self, orm):\r
+        \r
+        # Adding model 'NodeRevision'\r
+        db.create_table('forum_noderevision', (\r
+            ('node', self.gf('django.db.models.fields.related.ForeignKey')(related_name='revisions', to=orm['forum.Node'])),\r
+            ('body', self.gf('django.db.models.fields.TextField')()),\r
+            ('author', self.gf('django.db.models.fields.related.ForeignKey')(related_name='noderevisions', to=orm['forum.User'])),\r
+            ('tagnames', self.gf('django.db.models.fields.CharField')(max_length=125)),\r
+            ('title', self.gf('django.db.models.fields.CharField')(max_length=300)),\r
+            ('summary', self.gf('django.db.models.fields.CharField')(max_length=300)),\r
+            ('revised_at', self.gf('django.db.models.fields.DateTimeField')()),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('revision', self.gf('django.db.models.fields.PositiveIntegerField')()),\r
+        ))\r
+        db.send_create_signal('forum', ['NodeRevision'])\r
+\r
+        # Deleting field 'Vote.object_id'\r
+        db.delete_column(u'vote', 'object_id')\r
+\r
+        # Deleting field 'Vote.content_type'\r
+        db.delete_column(u'vote', 'content_type_id')\r
+\r
+        # Deleting field 'Comment.object_id'\r
+        db.delete_column(u'comment', 'object_id')\r
+\r
+        # Deleting field 'Comment.content_type'\r
+        db.delete_column(u'comment', 'content_type_id')\r
+\r
+        # Deleting field 'FlaggedItem.object_id'\r
+        db.delete_column(u'flagged_item', 'object_id')\r
+\r
+        # Deleting field 'FlaggedItem.content_type'\r
+        db.delete_column(u'flagged_item', 'content_type_id')\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        \r
+        # Deleting model 'NodeRevision'\r
+        db.delete_table('forum_noderevision')\r
+\r
+        # Adding field 'Vote.object_id'\r
+        db.add_column(u'vote', 'object_id', self.gf('django.db.models.fields.PositiveIntegerField')(default=1), keep_default=False)\r
+\r
+        # Adding field 'Vote.content_type'\r
+        db.add_column(u'vote', 'content_type', self.gf('django.db.models.fields.related.ForeignKey')(default=1, to=orm['contenttypes.ContentType']), keep_default=False)\r
+\r
+        # Adding field 'Comment.object_id'\r
+        db.add_column(u'comment', 'object_id', self.gf('django.db.models.fields.PositiveIntegerField')(default=1), keep_default=False)\r
+\r
+        # Adding field 'Comment.content_type'\r
+        db.add_column(u'comment', 'content_type', self.gf('django.db.models.fields.related.ForeignKey')(default=1, to=orm['contenttypes.ContentType']), keep_default=False)\r
+\r
+        # Adding field 'FlaggedItem.object_id'\r
+        db.add_column(u'flagged_item', 'object_id', self.gf('django.db.models.fields.PositiveIntegerField')(default=1), keep_default=False)\r
+\r
+        # Adding field 'FlaggedItem.content_type'\r
+        db.add_column(u'flagged_item', 'content_type', self.gf('django.db.models.fields.related.ForeignKey')(default=1, to=orm['contenttypes.ContentType']), keep_default=False)\r
+    \r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.anonymousanswer': {\r
+            'Meta': {'object_name': 'AnonymousAnswer'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_answers'", 'to': "orm['forum.Question']"}),\r
+            'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.anonymousquestion': {\r
+            'Meta': {'object_name': 'AnonymousQuestion'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),\r
+            'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.answer': {\r
+            'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"},\r
+            'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'accepted_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['forum.User']"}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_answers'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'html': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_answers'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'null': 'True'}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['forum.Question']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.answerrevision': {\r
+            'Meta': {'object_name': 'AnswerRevision', 'db_table': "u'answer_revision'"},\r
+            'answer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Answer']"}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answerrevisions'", 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}),\r
+            'text': ('django.db.models.fields.TextField', [], {})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('content_type', 'object_id', 'user', 'badge'),)", 'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.comment': {\r
+            'Meta': {'object_name': 'Comment', 'db_table': "u'comment'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'comment': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_comments'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'liked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'comments_liked'", 'through': "'LikedComment'", 'to': "orm['forum.User']"}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.favoritequestion': {\r
+            'Meta': {'unique_together': "(('question', 'user'),)", 'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.flaggeditem': {\r
+            'Meta': {'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.likedcomment': {\r
+            'Meta': {'object_name': 'LikedComment'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'comment': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Comment']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'childs'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.question': {\r
+            'Meta': {'object_name': 'Question', 'db_table': "u'question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'answer_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questions'", 'to': "orm['forum.User']"}),\r
+            'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['forum.User']"}),\r
+            'favourite_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'followed_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'followed_questions'", 'to': "orm['forum.User']"}),\r
+            'html': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'to': "orm['forum.User']"}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'null': 'True'}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'questions'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'view_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.questionrevision': {\r
+            'Meta': {'object_name': 'QuestionRevision', 'db_table': "u'question_revision'"},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questionrevisions'", 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Question']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 14, 12, 14, 26, 755000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.repute': {\r
+            'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'user_previous_rep': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 15, 12, 14, 35, 357000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'object_name': 'Vote', 'db_table': "u'vote'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'vote': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0009_convert_revisions.py b/forum/modules/template_loader.py/forum/migrations/0009_convert_revisions.py
new file mode 100644 (file)
index 0000000..6b06ed9
--- /dev/null
@@ -0,0 +1,414 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import DataMigration\r
+from django.db import models\r
+from forum.migrations import ProgressBar\r
+\r
+class Migration(DataMigration):\r
+    \r
+    def forwards(self, orm):\r
+        #Converting question revisions\r
+        qr_count = orm.QuestionRevision.objects.all().count()\r
+        print "\nConverting %d question revisions:" % qr_count\r
+        progress = ProgressBar(qr_count)\r
+\r
+        for q in orm.QuestionRevision.objects.order_by('id'):\r
+            revision = orm.NodeRevision(\r
+                node=q.question.node_ptr,\r
+                title=q.title,\r
+                summary=q.summary,\r
+                tagnames=q.tagnames,\r
+                revision=q.revision,\r
+                author=q.author,\r
+                revised_at=q.revised_at,\r
+                body=q.text,\r
+            )\r
+\r
+            revision.save()\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+\r
+\r
+        #Converting answer revisions\r
+        ar_count = orm.AnswerRevision.objects.all().count()\r
+        print "\nConverting %d answer revisions:" % ar_count\r
+        progress = ProgressBar(ar_count)\r
+\r
+        for a in orm.AnswerRevision.objects.order_by('id'):\r
+            revision = orm.NodeRevision(\r
+                summary=a.summary,\r
+                node=a.answer.node_ptr,\r
+                revision=a.revision,\r
+                author=a.author,\r
+                revised_at=a.revised_at,\r
+                body=a.text,\r
+            )\r
+\r
+            revision.save()\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        "Write your backwards methods here."\r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.anonymousanswer': {\r
+            'Meta': {'object_name': 'AnonymousAnswer'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_answers'", 'to': "orm['forum.Question']"}),\r
+            'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.anonymousquestion': {\r
+            'Meta': {'object_name': 'AnonymousQuestion'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),\r
+            'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.answer': {\r
+            'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"},\r
+            'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'accepted_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['forum.User']"}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_answers'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'html': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_answers'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'null': 'True'}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['forum.Question']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.answerrevision': {\r
+            'Meta': {'object_name': 'AnswerRevision', 'db_table': "u'answer_revision'"},\r
+            'answer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Answer']"}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answerrevisions'", 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}),\r
+            'text': ('django.db.models.fields.TextField', [], {})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('content_type', 'object_id', 'user', 'badge'),)", 'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.comment': {\r
+            'Meta': {'object_name': 'Comment', 'db_table': "u'comment'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'comment': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_comments'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'liked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'comments_liked'", 'through': "'LikedComment'", 'to': "orm['forum.User']"}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.favoritequestion': {\r
+            'Meta': {'unique_together': "(('question', 'user'),)", 'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.flaggeditem': {\r
+            'Meta': {'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.likedcomment': {\r
+            'Meta': {'object_name': 'LikedComment'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'comment': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Comment']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'childs'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.question': {\r
+            'Meta': {'object_name': 'Question', 'db_table': "u'question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'answer_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questions'", 'to': "orm['forum.User']"}),\r
+            'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['forum.User']"}),\r
+            'favourite_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'followed_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'followed_questions'", 'to': "orm['forum.User']"}),\r
+            'html': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'to': "orm['forum.User']"}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'null': 'True'}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'questions'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'view_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.questionrevision': {\r
+            'Meta': {'object_name': 'QuestionRevision', 'db_table': "u'question_revision'"},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questionrevisions'", 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Question']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 14, 12, 14, 26, 755000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.repute': {\r
+            'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'user_previous_rep': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 15, 12, 14, 35, 357000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'object_name': 'Vote', 'db_table': "u'vote'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'vote': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0010_auto__del_questionrevision__del_answerrevision__del_field_answer_vote_.py b/forum/modules/template_loader.py/forum/migrations/0010_auto__del_questionrevision__del_answerrevision__del_field_answer_vote_.py
new file mode 100644 (file)
index 0000000..8baaf67
--- /dev/null
@@ -0,0 +1,576 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import SchemaMigration\r
+from django.db import models\r
+\r
+class Migration(SchemaMigration):\r
+    \r
+    def forwards(self, orm):\r
+        \r
+        # Deleting model 'QuestionRevision'\r
+        db.delete_table(u'question_revision')\r
+\r
+        # Deleting model 'AnswerRevision'\r
+        db.delete_table(u'answer_revision')\r
+\r
+        # Deleting field 'Answer.vote_up_count'\r
+        db.delete_column(u'answer', 'vote_up_count')\r
+\r
+        # Deleting field 'Answer.author'\r
+        db.delete_column(u'answer', 'author_id')\r
+\r
+        # Deleting field 'Answer.deleted'\r
+        db.delete_column(u'answer', 'deleted')\r
+\r
+        # Deleting field 'Answer.question'\r
+        db.delete_column(u'answer', 'question_id')\r
+\r
+        # Deleting field 'Answer.html'\r
+        db.delete_column(u'answer', 'html')\r
+\r
+        # Deleting field 'Answer.offensive_flag_count'\r
+        db.delete_column(u'answer', 'offensive_flag_count')\r
+\r
+        # Deleting field 'Answer.deleted_by'\r
+        db.delete_column(u'answer', 'deleted_by_id')\r
+\r
+        # Deleting field 'Answer.comment_count'\r
+        db.delete_column(u'answer', 'comment_count')\r
+\r
+        # Deleting field 'Answer.score'\r
+        db.delete_column(u'answer', 'score')\r
+\r
+        # Deleting field 'Answer.vote_down_count'\r
+        db.delete_column(u'answer', 'vote_down_count')\r
+\r
+        # Deleting field 'Answer.added_at'\r
+        db.delete_column(u'answer', 'added_at')\r
+\r
+        # Deleting field 'Answer.last_edited_by'\r
+        db.delete_column(u'answer', 'last_edited_by_id')\r
+\r
+        # Deleting field 'Answer.deleted_at'\r
+        db.delete_column(u'answer', 'deleted_at')\r
+\r
+        # Deleting field 'Answer.id'\r
+        db.delete_column(u'answer', 'id')\r
+\r
+        # Deleting field 'Answer.last_edited_at'\r
+        db.delete_column(u'answer', 'last_edited_at')\r
+\r
+        # Changing field 'Answer.node_ptr'\r
+        db.alter_column(u'answer', 'node_ptr_id', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['forum.Node'], unique=True))\r
+        db.create_primary_key(u'answer', ['node_ptr_id'])\r
+\r
+        # Deleting field 'Question.vote_up_count'\r
+        db.delete_column(u'question', 'vote_up_count')\r
+\r
+        # Deleting field 'Question.offensive_flag_count'\r
+        db.delete_column(u'question', 'offensive_flag_count')\r
+\r
+        # Deleting field 'Question.summary'\r
+        db.delete_column(u'question', 'summary')\r
+\r
+        # Deleting field 'Question.id'\r
+        db.delete_column(u'question', 'id')\r
+\r
+        # Deleting field 'Question.deleted_at'\r
+        db.delete_column(u'question', 'deleted_at')\r
+\r
+        # Deleting field 'Question.score'\r
+        db.delete_column(u'question', 'score')\r
+\r
+        # Deleting field 'Question.author'\r
+        db.delete_column(u'question', 'author_id')\r
+\r
+        # Deleting field 'Question.comment_count'\r
+        db.delete_column(u'question', 'comment_count')\r
+\r
+        # Deleting field 'Question.html'\r
+        db.delete_column(u'question', 'html')\r
+\r
+        # Deleting field 'Question.vote_down_count'\r
+        db.delete_column(u'question', 'vote_down_count')\r
+\r
+        # Deleting field 'Question.last_edited_by'\r
+        db.delete_column(u'question', 'last_edited_by_id')\r
+\r
+        # Deleting field 'Question.deleted'\r
+        db.delete_column(u'question', 'deleted')\r
+\r
+        # Deleting field 'Question.tagnames'\r
+        db.delete_column(u'question', 'tagnames')\r
+\r
+        # Deleting field 'Question.title'\r
+        db.delete_column(u'question', 'title')\r
+\r
+        # Deleting field 'Question.added_at'\r
+        db.delete_column(u'question', 'added_at')\r
+\r
+        # Deleting field 'Question.deleted_by'\r
+        db.delete_column(u'question', 'deleted_by_id')\r
+\r
+        # Deleting field 'Question.last_edited_at'\r
+        db.delete_column(u'question', 'last_edited_at')\r
+\r
+        # Removing M2M table for field followed_by on 'Question'\r
+        db.delete_table('question_followed_by')\r
+\r
+        # Removing M2M table for field tags on 'Question'\r
+        db.delete_table('question_tags')\r
+\r
+        # Changing field 'Question.node_ptr'\r
+        db.alter_column(u'question', 'node_ptr_id', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['forum.Node'], unique=True))\r
+        db.create_primary_key(u'question', ['node_ptr_id'])        \r
+    \r
+    \r
+    def backwards(self, orm):\r
+        \r
+        # Adding model 'QuestionRevision'\r
+        db.create_table(u'question_revision', (\r
+            ('author', self.gf('django.db.models.fields.related.ForeignKey')(related_name='questionrevisions', to=orm['forum.User'])),\r
+            ('tagnames', self.gf('django.db.models.fields.CharField')(max_length=125)),\r
+            ('text', self.gf('django.db.models.fields.TextField')()),\r
+            ('title', self.gf('django.db.models.fields.CharField')(max_length=300)),\r
+            ('question', self.gf('django.db.models.fields.related.ForeignKey')(related_name='revisions', to=orm['forum.Question'])),\r
+            ('revised_at', self.gf('django.db.models.fields.DateTimeField')()),\r
+            ('summary', self.gf('django.db.models.fields.CharField')(max_length=300, blank=True)),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('revision', self.gf('django.db.models.fields.PositiveIntegerField')()),\r
+        ))\r
+        db.send_create_signal('forum', ['QuestionRevision'])\r
+\r
+        # Adding model 'AnswerRevision'\r
+        db.create_table(u'answer_revision', (\r
+            ('author', self.gf('django.db.models.fields.related.ForeignKey')(related_name='answerrevisions', to=orm['forum.User'])),\r
+            ('text', self.gf('django.db.models.fields.TextField')()),\r
+            ('revised_at', self.gf('django.db.models.fields.DateTimeField')()),\r
+            ('summary', self.gf('django.db.models.fields.CharField')(max_length=300, blank=True)),\r
+            ('answer', self.gf('django.db.models.fields.related.ForeignKey')(related_name='revisions', to=orm['forum.Answer'])),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('revision', self.gf('django.db.models.fields.PositiveIntegerField')()),\r
+        ))\r
+        db.send_create_signal('forum', ['AnswerRevision'])\r
+\r
+        # Adding field 'Answer.vote_up_count'\r
+        db.add_column(u'answer', 'vote_up_count', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)\r
+\r
+        # Adding field 'Answer.author'\r
+        db.add_column(u'answer', 'author', self.gf('django.db.models.fields.related.ForeignKey')(default=1, related_name='answers', to=orm['forum.User']), keep_default=False)\r
+\r
+        # Adding field 'Answer.deleted'\r
+        db.add_column(u'answer', 'deleted', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True), keep_default=False)\r
+\r
+        # Adding field 'Answer.question'\r
+        db.add_column(u'answer', 'question', self.gf('django.db.models.fields.related.ForeignKey')(default=1, related_name='answers', to=orm['forum.Question']), keep_default=False)\r
+\r
+        # Adding field 'Answer.html'\r
+        db.add_column(u'answer', 'html', self.gf('django.db.models.fields.TextField')(default=1), keep_default=False)\r
+\r
+        # Adding field 'Answer.offensive_flag_count'\r
+        db.add_column(u'answer', 'offensive_flag_count', self.gf('django.db.models.fields.SmallIntegerField')(default=0), keep_default=False)\r
+\r
+        # Adding field 'Answer.deleted_by'\r
+        db.add_column(u'answer', 'deleted_by', self.gf('django.db.models.fields.related.ForeignKey')(related_name='deleted_answers', null=True, to=orm['forum.User'], blank=True), keep_default=False)\r
+\r
+        # Adding field 'Answer.comment_count'\r
+        db.add_column(u'answer', 'comment_count', self.gf('django.db.models.fields.PositiveIntegerField')(default=0), keep_default=False)\r
+\r
+        # Adding field 'Answer.score'\r
+        db.add_column(u'answer', 'score', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)\r
+\r
+        # Adding field 'Answer.vote_down_count'\r
+        db.add_column(u'answer', 'vote_down_count', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)\r
+\r
+        # Adding field 'Answer.added_at'\r
+        db.add_column(u'answer', 'added_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now), keep_default=False)\r
+\r
+        # Adding field 'Answer.last_edited_by'\r
+        db.add_column(u'answer', 'last_edited_by', self.gf('django.db.models.fields.related.ForeignKey')(related_name='last_edited_answers', null=True, to=orm['forum.User'], blank=True), keep_default=False)\r
+\r
+        # Adding field 'Answer.deleted_at'\r
+        db.add_column(u'answer', 'deleted_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True), keep_default=False)\r
+\r
+        # Adding field 'Answer.id'\r
+        db.add_column(u'answer', 'id', self.gf('django.db.models.fields.AutoField')(default=1, primary_key=True), keep_default=False)\r
+\r
+        # Adding field 'Answer.last_edited_at'\r
+        db.add_column(u'answer', 'last_edited_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True), keep_default=False)\r
+\r
+        # Changing field 'Answer.node_ptr'\r
+        db.alter_column(u'answer', 'node_ptr_id', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['forum.Node'], unique=True, null=True))\r
+\r
+        # Adding field 'Question.vote_up_count'\r
+        db.add_column(u'question', 'vote_up_count', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)\r
+\r
+        # Adding field 'Question.offensive_flag_count'\r
+        db.add_column(u'question', 'offensive_flag_count', self.gf('django.db.models.fields.SmallIntegerField')(default=0), keep_default=False)\r
+\r
+        # Adding field 'Question.summary'\r
+        db.add_column(u'question', 'summary', self.gf('django.db.models.fields.CharField')(default=1, max_length=180), keep_default=False)\r
+\r
+        # Adding field 'Question.id'\r
+        db.add_column(u'question', 'id', self.gf('django.db.models.fields.AutoField')(default=1, primary_key=True), keep_default=False)\r
+\r
+        # Adding field 'Question.deleted_at'\r
+        db.add_column(u'question', 'deleted_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True), keep_default=False)\r
+\r
+        # Adding field 'Question.score'\r
+        db.add_column(u'question', 'score', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)\r
+\r
+        # Adding field 'Question.author'\r
+        db.add_column(u'question', 'author', self.gf('django.db.models.fields.related.ForeignKey')(default=1, related_name='questions', to=orm['forum.User']), keep_default=False)\r
+\r
+        # Adding field 'Question.comment_count'\r
+        db.add_column(u'question', 'comment_count', self.gf('django.db.models.fields.PositiveIntegerField')(default=0), keep_default=False)\r
+\r
+        # Adding field 'Question.html'\r
+        db.add_column(u'question', 'html', self.gf('django.db.models.fields.TextField')(default=1), keep_default=False)\r
+\r
+        # Adding field 'Question.vote_down_count'\r
+        db.add_column(u'question', 'vote_down_count', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)\r
+\r
+        # Adding field 'Question.last_edited_by'\r
+        db.add_column(u'question', 'last_edited_by', self.gf('django.db.models.fields.related.ForeignKey')(related_name='last_edited_questions', null=True, to=orm['forum.User'], blank=True), keep_default=False)\r
+\r
+        # Adding field 'Question.deleted'\r
+        db.add_column(u'question', 'deleted', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True), keep_default=False)\r
+\r
+        # Adding field 'Question.tagnames'\r
+        db.add_column(u'question', 'tagnames', self.gf('django.db.models.fields.CharField')(default=1, max_length=125), keep_default=False)\r
+\r
+        # Adding field 'Question.title'\r
+        db.add_column(u'question', 'title', self.gf('django.db.models.fields.CharField')(default=1, max_length=300), keep_default=False)\r
+\r
+        # Adding field 'Question.added_at'\r
+        db.add_column(u'question', 'added_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now), keep_default=False)\r
+\r
+        # Adding field 'Question.deleted_by'\r
+        db.add_column(u'question', 'deleted_by', self.gf('django.db.models.fields.related.ForeignKey')(related_name='deleted_questions', null=True, to=orm['forum.User'], blank=True), keep_default=False)\r
+\r
+        # Adding field 'Question.last_edited_at'\r
+        db.add_column(u'question', 'last_edited_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True), keep_default=False)\r
+\r
+        # Adding M2M table for field followed_by on 'Question'\r
+        db.create_table(u'question_followed_by', (\r
+            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),\r
+            ('question', models.ForeignKey(orm['forum.question'], null=False)),\r
+            ('user', models.ForeignKey(orm['forum.user'], null=False))\r
+        ))\r
+        db.create_unique(u'question_followed_by', ['question_id', 'user_id'])\r
+\r
+        # Adding M2M table for field tags on 'Question'\r
+        db.create_table(u'question_tags', (\r
+            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),\r
+            ('question', models.ForeignKey(orm['forum.question'], null=False)),\r
+            ('tag', models.ForeignKey(orm['forum.tag'], null=False))\r
+        ))\r
+        db.create_unique(u'question_tags', ['question_id', 'tag_id'])\r
+\r
+        # Changing field 'Question.node_ptr'\r
+        db.alter_column(u'question', 'node_ptr_id', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['forum.Node'], unique=True, null=True))\r
+    \r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.anonymousanswer': {\r
+            'Meta': {'object_name': 'AnonymousAnswer'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_answers'", 'to': "orm['forum.Question']"}),\r
+            'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.anonymousquestion': {\r
+            'Meta': {'object_name': 'AnonymousQuestion'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),\r
+            'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.answer': {\r
+            'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"},\r
+            'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'accepted_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('content_type', 'object_id', 'user', 'badge'),)", 'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.comment': {\r
+            'Meta': {'object_name': 'Comment', 'db_table': "u'comment'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'comment': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_comments'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'liked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'comments_liked'", 'through': "'LikedComment'", 'to': "orm['forum.User']"}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.favoritequestion': {\r
+            'Meta': {'unique_together': "(('question', 'user'),)", 'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.flaggeditem': {\r
+            'Meta': {'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.likedcomment': {\r
+            'Meta': {'object_name': 'LikedComment'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'comment': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Comment']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'childs'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.question': {\r
+            'Meta': {'object_name': 'Question', 'db_table': "u'question'"},\r
+            'answer_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['forum.User']"}),\r
+            'favourite_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'to': "orm['forum.User']"}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True'}),\r
+            'subscribers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscriptions'", 'through': "'QuestionSubscription'", 'to': "orm['forum.User']"}),\r
+            'view_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 14, 12, 30, 8, 362000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.repute': {\r
+            'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'user_previous_rep': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 15, 12, 30, 22, 477000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'object_name': 'Vote', 'db_table': "u'vote'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'vote': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0011_auto__add_field_node_active_revision.py b/forum/modules/template_loader.py/forum/migrations/0011_auto__add_field_node_active_revision.py
new file mode 100644 (file)
index 0000000..940f37f
--- /dev/null
@@ -0,0 +1,323 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import SchemaMigration\r
+from django.db import models\r
+\r
+class Migration(SchemaMigration):\r
+    \r
+    def forwards(self, orm):\r
+        \r
+        # Adding field 'Node.active_revision'\r
+        db.add_column('forum_node', 'active_revision', self.gf('django.db.models.fields.related.OneToOneField')(related_name='active', unique=True, null=True, to=orm['forum.NodeRevision']), keep_default=False)\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        \r
+        # Deleting field 'Node.active_revision'\r
+        db.delete_column('forum_node', 'active_revision_id')\r
+    \r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.anonymousanswer': {\r
+            'Meta': {'object_name': 'AnonymousAnswer'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_answers'", 'to': "orm['forum.Question']"}),\r
+            'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.anonymousquestion': {\r
+            'Meta': {'object_name': 'AnonymousQuestion'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),\r
+            'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.answer': {\r
+            'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"},\r
+            'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'accepted_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('content_type', 'object_id', 'user', 'badge'),)", 'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.comment': {\r
+            'Meta': {'object_name': 'Comment', 'db_table': "u'comment'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'comment': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_comments'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'liked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'comments_liked'", 'through': "'LikedComment'", 'to': "orm['forum.User']"}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.favoritequestion': {\r
+            'Meta': {'unique_together': "(('question', 'user'),)", 'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.flaggeditem': {\r
+            'Meta': {'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.likedcomment': {\r
+            'Meta': {'object_name': 'LikedComment'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'comment': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Comment']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.question': {\r
+            'Meta': {'object_name': 'Question', 'db_table': "u'question'"},\r
+            'answer_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['forum.User']"}),\r
+            'favourite_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'to': "orm['forum.User']"}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True'}),\r
+            'subscribers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscriptions'", 'through': "'QuestionSubscription'", 'to': "orm['forum.User']"}),\r
+            'view_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 14, 17, 56, 17, 351000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.repute': {\r
+            'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'user_previous_rep': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 15, 17, 56, 17, 557000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'object_name': 'Vote', 'db_table': "u'vote'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'vote': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0012_set_active_revision.py b/forum/modules/template_loader.py/forum/migrations/0012_set_active_revision.py
new file mode 100644 (file)
index 0000000..24c419a
--- /dev/null
@@ -0,0 +1,327 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import DataMigration\r
+from django.db import models\r
+\r
+class Migration(DataMigration):\r
+    \r
+    def forwards(self, orm):\r
+        for n in orm.Node.objects.all():\r
+            try:\r
+                n.active_revision = n.revisions.order_by('-id')[0]\r
+                n.save()\r
+            except:\r
+                r = orm.NodeRevision(author=n.author, body=n.body, title=n.title, revised_at=datetime.datetime.now(),\r
+                                 tagnames=n.tagnames, summary='Initial Revision', revision=1, node=n)\r
+                r.save()\r
+                n.active_revision = r\r
+                n.save()\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        "Write your backwards methods here."\r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.anonymousanswer': {\r
+            'Meta': {'object_name': 'AnonymousAnswer'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_answers'", 'to': "orm['forum.Question']"}),\r
+            'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.anonymousquestion': {\r
+            'Meta': {'object_name': 'AnonymousQuestion'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),\r
+            'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'text': ('django.db.models.fields.TextField', [], {}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.answer': {\r
+            'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"},\r
+            'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'accepted_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('content_type', 'object_id', 'user', 'badge'),)", 'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.comment': {\r
+            'Meta': {'object_name': 'Comment', 'db_table': "u'comment'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'comment': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_comments'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'liked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'comments_liked'", 'through': "'LikedComment'", 'to': "orm['forum.User']"}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.favoritequestion': {\r
+            'Meta': {'unique_together': "(('question', 'user'),)", 'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.flaggeditem': {\r
+            'Meta': {'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.likedcomment': {\r
+            'Meta': {'object_name': 'LikedComment'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'comment': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Comment']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.question': {\r
+            'Meta': {'object_name': 'Question', 'db_table': "u'question'"},\r
+            'answer_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['forum.User']"}),\r
+            'favourite_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'to': "orm['forum.User']"}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True'}),\r
+            'subscribers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscriptions'", 'through': "'QuestionSubscription'", 'to': "orm['forum.User']"}),\r
+            'view_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 14, 17, 56, 41, 918000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.repute': {\r
+            'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'user_previous_rep': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 15, 17, 56, 41, 986000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'object_name': 'Vote', 'db_table': "u'vote'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'vote': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0013_auto__del_anonymousquestion__del_anonymousanswer__add_anonymousnode.py b/forum/modules/template_loader.py/forum/migrations/0013_auto__del_anonymousquestion__del_anonymousanswer__add_anonymousnode.py
new file mode 100644 (file)
index 0000000..d203297
--- /dev/null
@@ -0,0 +1,344 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import SchemaMigration\r
+from django.db import models\r
+\r
+class Migration(SchemaMigration):\r
+    \r
+    def forwards(self, orm):\r
+        \r
+        # Deleting model 'AnonymousQuestion'\r
+        db.delete_table('forum_anonymousquestion')\r
+\r
+        # Deleting model 'AnonymousAnswer'\r
+        db.delete_table('forum_anonymousanswer')\r
+\r
+        # Adding model 'AnonymousNode'\r
+        db.create_table('forum_anonymousnode', (\r
+            ('convertible_to', self.gf('django.db.models.fields.CharField')(default='node', max_length=16)),\r
+            ('validation_hash', self.gf('django.db.models.fields.related.ForeignKey')(related_name='anonymous_content', to=orm['forum.Node'])),\r
+            ('node_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['forum.Node'], unique=True, primary_key=True)),\r
+        ))\r
+        db.send_create_signal('forum', ['AnonymousNode'])\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        \r
+        # Adding model 'AnonymousQuestion'\r
+        db.create_table('forum_anonymousquestion', (\r
+            ('wiki', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('ip_addr', self.gf('django.db.models.fields.IPAddressField')(max_length=15)),\r
+            ('title', self.gf('django.db.models.fields.CharField')(max_length=300)),\r
+            ('tagnames', self.gf('django.db.models.fields.CharField')(max_length=125)),\r
+            ('text', self.gf('django.db.models.fields.TextField')()),\r
+            ('author', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.User'], null=True)),\r
+            ('added_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+            ('summary', self.gf('django.db.models.fields.CharField')(max_length=180)),\r
+            ('session_key', self.gf('django.db.models.fields.CharField')(max_length=40)),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+        ))\r
+        db.send_create_signal('forum', ['AnonymousQuestion'])\r
+\r
+        # Adding model 'AnonymousAnswer'\r
+        db.create_table('forum_anonymousanswer', (\r
+            ('wiki', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('ip_addr', self.gf('django.db.models.fields.IPAddressField')(max_length=15)),\r
+            ('author', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.User'], null=True)),\r
+            ('text', self.gf('django.db.models.fields.TextField')()),\r
+            ('question', self.gf('django.db.models.fields.related.ForeignKey')(related_name='anonymous_answers', to=orm['forum.Question'])),\r
+            ('added_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+            ('summary', self.gf('django.db.models.fields.CharField')(max_length=180)),\r
+            ('session_key', self.gf('django.db.models.fields.CharField')(max_length=40)),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+        ))\r
+        db.send_create_signal('forum', ['AnonymousAnswer'])\r
+\r
+        # Deleting model 'AnonymousNode'\r
+        db.delete_table('forum_anonymousnode')\r
+    \r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.anonymousnode': {\r
+            'Meta': {'object_name': 'AnonymousNode', '_ormbases': ['forum.Node']},\r
+            'convertible_to': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'validation_hash': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_content'", 'to': "orm['forum.Node']"})\r
+        },\r
+        'forum.answer': {\r
+            'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"},\r
+            'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'accepted_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('content_type', 'object_id', 'user', 'badge'),)", 'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.comment': {\r
+            'Meta': {'object_name': 'Comment', 'db_table': "u'comment'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'comment': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_comments'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'liked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'comments_liked'", 'through': "'LikedComment'", 'to': "orm['forum.User']"}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.favoritequestion': {\r
+            'Meta': {'unique_together': "(('question', 'user'),)", 'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.flaggeditem': {\r
+            'Meta': {'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.likedcomment': {\r
+            'Meta': {'object_name': 'LikedComment'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'comment': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Comment']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.question': {\r
+            'Meta': {'object_name': 'Question', 'db_table': "u'question'"},\r
+            'answer_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['forum.User']"}),\r
+            'favourite_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'to': "orm['forum.User']"}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True'}),\r
+            'subscribers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscriptions'", 'through': "'QuestionSubscription'", 'to': "orm['forum.User']"}),\r
+            'view_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 14, 18, 42, 39, 311000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.repute': {\r
+            'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'user_previous_rep': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 15, 18, 42, 39, 525000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'object_name': 'Vote', 'db_table': "u'vote'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'vote': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0014_auto__add_field_question_accepted_answer.py b/forum/modules/template_loader.py/forum/migrations/0014_auto__add_field_question_accepted_answer.py
new file mode 100644 (file)
index 0000000..e73c960
--- /dev/null
@@ -0,0 +1,309 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import SchemaMigration\r
+from django.db import models\r
+from django.conf import settings\r
+\r
+class Migration(SchemaMigration):\r
+    \r
+    def forwards(self, orm):\r
+        \r
+        # Adding field 'Question.accepted_answer'\r
+        db.add_column(u'question', 'accepted_answer', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['forum.Answer'], unique=True, null=True), keep_default=False)\r
+\r
+        #if db.backend_name == "postgres" and not "pgfulltext" in settings.DISABLED_MODULES:\r
+        #    db.execute("DROP TRIGGER tsvectorupdate ON question;")\r
+        #    db.execute("ALTER TABLE question DROP COLUMN tsv;")\r
+    \r
+    def backwards(self, orm):\r
+        \r
+        # Deleting field 'Question.accepted_answer'\r
+        db.delete_column(u'question', 'accepted_answer_id')\r
+    \r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.anonymousnode': {\r
+            'Meta': {'object_name': 'AnonymousNode', '_ormbases': ['forum.Node']},\r
+            'convertible_to': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'validation_hash': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_content'", 'to': "orm['forum.Node']"})\r
+        },\r
+        'forum.answer': {\r
+            'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"},\r
+            'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'accepted_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('content_type', 'object_id', 'user', 'badge'),)", 'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.comment': {\r
+            'Meta': {'object_name': 'Comment', 'db_table': "u'comment'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'comment': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_comments'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'liked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'comments_liked'", 'through': "'LikedComment'", 'to': "orm['forum.User']"}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.favoritequestion': {\r
+            'Meta': {'unique_together': "(('question', 'user'),)", 'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.flaggeditem': {\r
+            'Meta': {'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.likedcomment': {\r
+            'Meta': {'object_name': 'LikedComment'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'comment': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Comment']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.question': {\r
+            'Meta': {'object_name': 'Question', 'db_table': "u'question'"},\r
+            'accepted_answer': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Answer']", 'unique': 'True', 'null': 'True'}),\r
+            'answer_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['forum.User']"}),\r
+            'favourite_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'to': "orm['forum.User']"}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True'}),\r
+            'subscribers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscriptions'", 'through': "'QuestionSubscription'", 'to': "orm['forum.User']"}),\r
+            'view_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 16, 11, 5, 41, 763000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.repute': {\r
+            'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'user_previous_rep': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 17, 11, 5, 42, 36000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'object_name': 'Vote', 'db_table': "u'vote'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'vote': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0015_accepted_answer_changes.py b/forum/modules/template_loader.py/forum/migrations/0015_accepted_answer_changes.py
new file mode 100644 (file)
index 0000000..ee98647
--- /dev/null
@@ -0,0 +1,320 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import DataMigration\r
+from django.db import models\r
+from forum.migrations import ProgressBar\r
+\r
+class Migration(DataMigration):\r
+    \r
+    def forwards(self, orm):\r
+        q_count = orm.Node.objects.filter(node_type="question").count()\r
+        print "\nConverting %d questions:" % q_count\r
+        progress = ProgressBar(q_count)\r
+\r
+        for n in orm.Node.objects.filter(node_type="question"):\r
+            q = orm.Question.objects.get(node_ptr=n)\r
+            if q.answer_accepted:\r
+                accepted = list(orm.Answer.objects.filter(node_ptr__parent=n, accepted=True))\r
+\r
+                if len(accepted):\r
+                    accepted = accepted[0]\r
+                    q.accepted_answer = accepted\r
+                else:\r
+                    q.answer_accepted = False\r
+\r
+                q.save()           \r
+\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        "Write your backwards methods here."\r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.anonymousnode': {\r
+            'Meta': {'object_name': 'AnonymousNode', '_ormbases': ['forum.Node']},\r
+            'convertible_to': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'validation_hash': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_content'", 'to': "orm['forum.Node']"})\r
+        },\r
+        'forum.answer': {\r
+            'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"},\r
+            'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'accepted_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('content_type', 'object_id', 'user', 'badge'),)", 'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.comment': {\r
+            'Meta': {'object_name': 'Comment', 'db_table': "u'comment'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'comment': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_comments'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'liked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'comments_liked'", 'through': "'LikedComment'", 'to': "orm['forum.User']"}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.favoritequestion': {\r
+            'Meta': {'unique_together': "(('question', 'user'),)", 'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.flaggeditem': {\r
+            'Meta': {'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.likedcomment': {\r
+            'Meta': {'object_name': 'LikedComment'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'comment': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Comment']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.question': {\r
+            'Meta': {'object_name': 'Question', 'db_table': "u'question'"},\r
+            'accepted_answer': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Answer']", 'unique': 'True', 'null': 'True'}),\r
+            'answer_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['forum.User']"}),\r
+            'favourite_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'to': "orm['forum.User']"}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'subscribers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscriptions'", 'through': "'QuestionSubscription'", 'to': "orm['forum.User']"}),\r
+            'view_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 16, 11, 6, 44, 202000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.repute': {\r
+            'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'user_previous_rep': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 17, 11, 6, 44, 279000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'object_name': 'Vote', 'db_table': "u'vote'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'vote': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0016_auto__del_field_question_answer_accepted__chg_field_question_node_ptr.py b/forum/modules/template_loader.py/forum/migrations/0016_auto__del_field_question_answer_accepted__chg_field_question_node_ptr.py
new file mode 100644 (file)
index 0000000..efa35d0
--- /dev/null
@@ -0,0 +1,310 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import SchemaMigration\r
+from django.db import models\r
+\r
+class Migration(SchemaMigration):\r
+    \r
+    def forwards(self, orm):\r
+        \r
+        # Deleting field 'Question.answer_accepted'\r
+        db.delete_column(u'question', 'answer_accepted')\r
+\r
+        # Changing field 'Question.node_ptr'\r
+        db.alter_column(u'question', 'node_ptr_id', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['forum.Node'], unique=True))\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        \r
+        # Adding field 'Question.answer_accepted'\r
+        db.add_column(u'question', 'answer_accepted', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True), keep_default=False)\r
+\r
+        # Changing field 'Question.node_ptr'\r
+        db.alter_column(u'question', 'node_ptr_id', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['forum.Node'], unique=True, primary_key=True))\r
+    \r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.anonymousnode': {\r
+            'Meta': {'object_name': 'AnonymousNode', '_ormbases': ['forum.Node']},\r
+            'convertible_to': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'validation_hash': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_content'", 'to': "orm['forum.Node']"})\r
+        },\r
+        'forum.answer': {\r
+            'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"},\r
+            'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'accepted_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('content_type', 'object_id', 'user', 'badge'),)", 'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.comment': {\r
+            'Meta': {'object_name': 'Comment', 'db_table': "u'comment'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'comment': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_comments'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'liked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'comments_liked'", 'through': "'LikedComment'", 'to': "orm['forum.User']"}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.favoritequestion': {\r
+            'Meta': {'unique_together': "(('question', 'user'),)", 'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.flaggeditem': {\r
+            'Meta': {'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.likedcomment': {\r
+            'Meta': {'object_name': 'LikedComment'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'comment': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Comment']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.question': {\r
+            'Meta': {'object_name': 'Question', 'db_table': "u'question'"},\r
+            'accepted_answer': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Answer']", 'unique': 'True', 'null': 'True'}),\r
+            'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['forum.User']"}),\r
+            'favourite_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'to': "orm['forum.User']"}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True'}),\r
+            'subscribers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscriptions'", 'through': "'QuestionSubscription'", 'to': "orm['forum.User']"}),\r
+            'view_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 16, 13, 28, 30, 313000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.repute': {\r
+            'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'user_previous_rep': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 17, 13, 28, 30, 540000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'object_name': 'Vote', 'db_table': "u'vote'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'vote': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0017_auto__add_field_repute_node__add_field_repute_canceled.py b/forum/modules/template_loader.py/forum/migrations/0017_auto__add_field_repute_node__add_field_repute_canceled.py
new file mode 100644 (file)
index 0000000..cb14267
--- /dev/null
@@ -0,0 +1,312 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import SchemaMigration\r
+from django.db import models\r
+\r
+class Migration(SchemaMigration):\r
+    \r
+    def forwards(self, orm):\r
+        \r
+        # Adding field 'Repute.node'\r
+        db.add_column(u'repute', 'node', self.gf('django.db.models.fields.related.ForeignKey')(related_name='reputes', null=True, to=orm['forum.Node']), keep_default=False)\r
+\r
+        # Adding field 'Repute.canceled'\r
+        db.add_column(u'repute', 'canceled', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True), keep_default=False)\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        \r
+        # Deleting field 'Repute.node'\r
+        db.delete_column(u'repute', 'node_id')\r
+\r
+        # Deleting field 'Repute.canceled'\r
+        db.delete_column(u'repute', 'canceled')\r
+    \r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.anonymousnode': {\r
+            'Meta': {'object_name': 'AnonymousNode', '_ormbases': ['forum.Node']},\r
+            'convertible_to': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'validation_hash': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_content'", 'to': "orm['forum.Node']"})\r
+        },\r
+        'forum.answer': {\r
+            'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"},\r
+            'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'accepted_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('content_type', 'object_id', 'user', 'badge'),)", 'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.comment': {\r
+            'Meta': {'object_name': 'Comment', 'db_table': "u'comment'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'comment': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_comments'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'liked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'comments_liked'", 'through': "'LikedComment'", 'to': "orm['forum.User']"}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.favoritequestion': {\r
+            'Meta': {'unique_together': "(('question', 'user'),)", 'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.flaggeditem': {\r
+            'Meta': {'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.likedcomment': {\r
+            'Meta': {'object_name': 'LikedComment'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'comment': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Comment']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.question': {\r
+            'Meta': {'object_name': 'Question', 'db_table': "u'question'"},\r
+            'accepted_answer': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'question_accepting'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Answer']"}),\r
+            'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['forum.User']"}),\r
+            'favourite_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'to': "orm['forum.User']"}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True'}),\r
+            'subscribers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscriptions'", 'through': "'QuestionSubscription'", 'to': "orm['forum.User']"}),\r
+            'view_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 16, 14, 18, 46, 625000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.repute': {\r
+            'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'user_previous_rep': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 17, 14, 18, 46, 835000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'object_name': 'Vote', 'db_table': "u'vote'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'vote': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0018_comments_to_node.py b/forum/modules/template_loader.py/forum/migrations/0018_comments_to_node.py
new file mode 100644 (file)
index 0000000..808bb0e
--- /dev/null
@@ -0,0 +1,376 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import DataMigration\r
+from django.db import models\r
+from forum.migrations import ProgressBar\r
+\r
+class Migration(DataMigration):\r
+    \r
+    def forwards(self, orm):\r
+        c_count = orm.Comment.objects.count()\r
+        print "\nConverting %d comments:" % c_count\r
+        progress = ProgressBar(c_count)\r
+\r
+        id_map = {}\r
+\r
+        for c in orm.Comment.objects.all():\r
+            node = orm.Node(\r
+                node_type='comment',\r
+                author=c.user,\r
+                added_at=c.added_at,\r
+                score=c.score,\r
+                vote_up_count=c.score,\r
+                vote_down_count=0,\r
+                offensive_flag_count=0,\r
+                last_edited_at=c.added_at,\r
+                last_edited_by=c.user,\r
+                body=c.comment,\r
+                deleted=c.deleted,\r
+                deleted_by=c.deleted_by,\r
+                deleted_at=c.deleted_at,\r
+                parent=c.node,\r
+            )\r
+            node.save()\r
+\r
+            id_map[c.id] = node\r
+\r
+            revision = orm.NodeRevision(\r
+                summary="Initial revsion",\r
+                revision=1,\r
+                revised_at=c.added_at,\r
+                body=c.comment,\r
+                author=c.user,\r
+                node=node,\r
+            )\r
+\r
+            revision.save()\r
+\r
+            node.active_revision = revision\r
+            node.save()\r
+\r
+            for v in orm.LikedComment.objects.filter(comment=c):\r
+                vote = orm.Vote(\r
+                    node=node,\r
+                    vote=1,\r
+                    voted_at=v.added_at,\r
+                    canceled=v.canceled,\r
+                    user=v.user,\r
+                )\r
+\r
+                vote.save()\r
+\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+\r
+        ctype = orm['contenttypes.ContentType'].objects.get(name="comment").id\r
+        ntype = orm['contenttypes.ContentType'].objects.get(name="node").id\r
+\r
+        #Converting activity\r
+        activities = orm.Activity.objects.filter(content_type__id=ctype)\r
+        activity_count = activities.count()\r
+        print "Converting %d activity references:" % activity_count\r
+        progress = ProgressBar(activity_count)\r
+\r
+        for a in activities:\r
+            node = id_map.get(a.object_id, None)\r
+            if node:\r
+                a.content_type_id = ntype\r
+                a.object_id = node.id\r
+                a.save()\r
+\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        "Write your backwards methods here."\r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.anonymousnode': {\r
+            'Meta': {'object_name': 'AnonymousNode', '_ormbases': ['forum.Node']},\r
+            'convertible_to': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'validation_hash': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_content'", 'to': "orm['forum.Node']"})\r
+        },\r
+        'forum.answer': {\r
+            'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"},\r
+            'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'accepted_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('content_type', 'object_id', 'user', 'badge'),)", 'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.comment': {\r
+            'Meta': {'object_name': 'Comment', 'db_table': "u'comment'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'comment': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_comments'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'liked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'comments_liked'", 'through': "'LikedComment'", 'to': "orm['forum.User']"}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.favoritequestion': {\r
+            'Meta': {'unique_together': "(('question', 'user'),)", 'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.flaggeditem': {\r
+            'Meta': {'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.likedcomment': {\r
+            'Meta': {'object_name': 'LikedComment'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'comment': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Comment']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.question': {\r
+            'Meta': {'object_name': 'Question', 'db_table': "u'question'"},\r
+            'accepted_answer': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'question_accepting'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Answer']"}),\r
+            'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['forum.User']"}),\r
+            'favourite_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'to': "orm['forum.User']"}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True'}),\r
+            'subscribers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscriptions'", 'through': "'QuestionSubscription'", 'to': "orm['forum.User']"}),\r
+            'view_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 16, 14, 19, 21, 765000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.repute': {\r
+            'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'user_previous_rep': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 17, 14, 19, 21, 837000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'object_name': 'Vote', 'db_table': "u'vote'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'vote': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0019_auto__del_likedcomment__del_comment__add_field_node_abs_parent__chg_fi.py b/forum/modules/template_loader.py/forum/migrations/0019_auto__del_likedcomment__del_comment__add_field_node_abs_parent__chg_fi.py
new file mode 100644 (file)
index 0000000..b6acebe
--- /dev/null
@@ -0,0 +1,322 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import SchemaMigration\r
+from django.db import models\r
+\r
+class Migration(SchemaMigration):\r
+    \r
+    def forwards(self, orm):\r
+        \r
+        # Deleting model 'LikedComment'\r
+        db.delete_table('forum_likedcomment')\r
+\r
+        # Deleting model 'Comment'\r
+        db.delete_table(u'comment')\r
+\r
+        # Adding field 'Node.abs_parent'\r
+        db.add_column('forum_node', 'abs_parent', self.gf('django.db.models.fields.related.ForeignKey')(related_name='all_children', null=True, to=orm['forum.Node']), keep_default=False)\r
+\r
+        # Changing field 'Question.last_activity_by'\r
+        db.alter_column(u'question', 'last_activity_by_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, to=orm['forum.User']))\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        \r
+        # Adding model 'LikedComment'\r
+        db.create_table('forum_likedcomment', (\r
+            ('comment', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.Comment'])),\r
+            ('canceled', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.User'])),\r
+            ('added_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+        ))\r
+        db.send_create_signal('forum', ['LikedComment'])\r
+\r
+        # Adding model 'Comment'\r
+        db.create_table(u'comment', (\r
+            ('comment', self.gf('django.db.models.fields.CharField')(max_length=300)),\r
+            ('node', self.gf('django.db.models.fields.related.ForeignKey')(related_name='comments', null=True, to=orm['forum.Node'])),\r
+            ('deleted', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('added_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+            ('deleted_by', self.gf('django.db.models.fields.related.ForeignKey')(related_name='deleted_comments', null=True, to=orm['forum.User'], blank=True)),\r
+            ('score', self.gf('django.db.models.fields.IntegerField')(default=0)),\r
+            ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='comments', to=orm['forum.User'])),\r
+            ('deleted_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+        ))\r
+        db.send_create_signal('forum', ['Comment'])\r
+\r
+        # Deleting field 'Node.abs_parent'\r
+        db.delete_column('forum_node', 'abs_parent_id')\r
+\r
+        # Changing field 'Question.last_activity_by'\r
+        db.alter_column(u'question', 'last_activity_by_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.User']))\r
+    \r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.anonymousnode': {\r
+            'Meta': {'object_name': 'AnonymousNode', '_ormbases': ['forum.Node']},\r
+            'convertible_to': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'validation_hash': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_content'", 'to': "orm['forum.Node']"})\r
+        },\r
+        'forum.answer': {\r
+            'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"},\r
+            'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'accepted_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('content_type', 'object_id', 'user', 'badge'),)", 'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.favoritequestion': {\r
+            'Meta': {'unique_together': "(('question', 'user'),)", 'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.flaggeditem': {\r
+            'Meta': {'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.question': {\r
+            'Meta': {'object_name': 'Question', 'db_table': "u'question'"},\r
+            'accepted_answer': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'question_accepting'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Answer']"}),\r
+            'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['forum.User']"}),\r
+            'favourite_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True'}),\r
+            'subscribers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscriptions'", 'through': "'QuestionSubscription'", 'to': "orm['forum.User']"}),\r
+            'view_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 17, 1, 11, 40, 975000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.repute': {\r
+            'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'user_previous_rep': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 18, 1, 11, 41, 269000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'object_name': 'Vote', 'db_table': "u'vote'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'vote': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0020_create_absolute_parents.py b/forum/modules/template_loader.py/forum/migrations/0020_create_absolute_parents.py
new file mode 100644 (file)
index 0000000..6a37403
--- /dev/null
@@ -0,0 +1,300 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import DataMigration\r
+from django.db import models\r
+from forum.migrations import ProgressBar\r
+\r
+class Migration(DataMigration):\r
+    \r
+    def forwards(self, orm):\r
+        def get_abs_par(n):\r
+            if n.parent:\r
+                return get_abs_par(n.parent)\r
+            else:\r
+                return n\r
+\r
+        n_count = orm.Node.objects.count()\r
+        print "\nConverting %d nodes:" % n_count\r
+        progress = ProgressBar(n_count)\r
+\r
+        for n in orm.Node.objects.all():\r
+            if n.parent:\r
+                n.abs_parent = get_abs_par(n)\r
+            else:\r
+                n.abs_parent = None\r
+            n.save()\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        "Write your backwards methods here."\r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.anonymousnode': {\r
+            'Meta': {'object_name': 'AnonymousNode', '_ormbases': ['forum.Node']},\r
+            'convertible_to': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'validation_hash': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_content'", 'to': "orm['forum.Node']"})\r
+        },\r
+        'forum.answer': {\r
+            'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"},\r
+            'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'accepted_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('content_type', 'object_id', 'user', 'badge'),)", 'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.favoritequestion': {\r
+            'Meta': {'unique_together': "(('question', 'user'),)", 'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.flaggeditem': {\r
+            'Meta': {'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.question': {\r
+            'Meta': {'object_name': 'Question', 'db_table': "u'question'"},\r
+            'accepted_answer': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'question_accepting'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Answer']"}),\r
+            'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['forum.User']"}),\r
+            'favourite_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True'}),\r
+            'subscribers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscriptions'", 'through': "'QuestionSubscription'", 'to': "orm['forum.User']"}),\r
+            'view_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 17, 1, 20, 29, 905000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.repute': {\r
+            'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'user_previous_rep': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 18, 1, 20, 29, 974000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'object_name': 'Vote', 'db_table': "u'vote'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'vote': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0021_create_new_pg_fts_triggers.py b/forum/modules/template_loader.py/forum/migrations/0021_create_new_pg_fts_triggers.py
new file mode 100644 (file)
index 0000000..16ef25b
--- /dev/null
@@ -0,0 +1,303 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import SchemaMigration\r
+from django.db import models\r
+from django.conf import settings\r
+\r
+class Migration(SchemaMigration):\r
+    \r
+    def forwards(self, orm):\r
+        if db.backend_name == "postgres" and not "pgfulltext" in settings.DISABLED_MODULES:\r
+            try:\r
+                import forum_modules.pgfulltext.management\r
+            except Exception, e:\r
+                pass\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        "Write your backwards methods here."\r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.anonymousnode': {\r
+            'Meta': {'object_name': 'AnonymousNode', '_ormbases': ['forum.Node']},\r
+            'convertible_to': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'validation_hash': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_content'", 'to': "orm['forum.Node']"})\r
+        },\r
+        'forum.answer': {\r
+            'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"},\r
+            'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'accepted_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('content_type', 'object_id', 'user', 'badge'),)", 'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.favoritequestion': {\r
+            'Meta': {'unique_together': "(('question', 'user'),)", 'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.flaggeditem': {\r
+            'Meta': {'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.openidassociation': {\r
+            'Meta': {'object_name': 'OpenIdAssociation'},\r
+            'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}),\r
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'issued': ('django.db.models.fields.IntegerField', [], {}),\r
+            'lifetime': ('django.db.models.fields.IntegerField', [], {}),\r
+            'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}),\r
+            'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'})\r
+        },\r
+        'forum.openidnonce': {\r
+            'Meta': {'object_name': 'OpenIdNonce'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),\r
+            'timestamp': ('django.db.models.fields.IntegerField', [], {})\r
+        },\r
+        'forum.question': {\r
+            'Meta': {'object_name': 'Question', 'db_table': "u'question'"},\r
+            'accepted_answer': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'question_accepting'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Answer']"}),\r
+            'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['forum.User']"}),\r
+            'favourite_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True'}),\r
+            'subscribers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscriptions'", 'through': "'QuestionSubscription'", 'to': "orm['forum.User']"}),\r
+            'view_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 17, 2, 50, 12, 337000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.repute': {\r
+            'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'user_previous_rep': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 18, 2, 50, 12, 421000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'object_name': 'Vote', 'db_table': "u'vote'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'vote': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0022_auto__add_actionrepute__add_action__add_favoritenode__del_field_node_v.py b/forum/modules/template_loader.py/forum/migrations/0022_auto__add_actionrepute__add_action__add_favoritenode__del_field_node_v.py
new file mode 100644 (file)
index 0000000..87b792e
--- /dev/null
@@ -0,0 +1,463 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import SchemaMigration\r
+from django.db import models\r
+\r
+class Migration(SchemaMigration):\r
+    \r
+    def forwards(self, orm):\r
+        \r
+        print "# Adding model 'ActionRepute'"\r
+        db.create_table('forum_actionrepute', (\r
+            ('action', self.gf('django.db.models.fields.related.ForeignKey')(related_name='reputes', to=orm['forum.Action'])),\r
+            ('by_canceled', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('value', self.gf('django.db.models.fields.IntegerField')(default=0)),\r
+            ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.User'])),\r
+        ))\r
+        db.send_create_signal('forum', ['ActionRepute'])\r
+\r
+        print "# Adding model 'Action'"\r
+        db.create_table('forum_action', (\r
+            ('node', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.Node'], null=True)),\r
+            ('extra', self.gf('django.db.models.fields.CharField')(max_length=255)),\r
+            ('canceled_by', self.gf('django.db.models.fields.related.ForeignKey')(related_name='canceled_actions', null=True, to=orm['forum.User'])),\r
+            ('canceled', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('action_date', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+            ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='actions', to=orm['forum.User'])),\r
+            ('action_type', self.gf('django.db.models.fields.CharField')(max_length=16)),\r
+            ('canceled_at', self.gf('django.db.models.fields.DateTimeField')(null=True)),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('ip', self.gf('django.db.models.fields.CharField')(max_length=16, null=True)),\r
+        ))\r
+        db.send_create_signal('forum', ['Action'])\r
+\r
+        print "# Deleting field 'Node.vote_up_count'"\r
+        db.delete_column('forum_node', 'vote_up_count')\r
+\r
+        print "# Deleting field 'Node.comment_count'"\r
+        db.delete_column('forum_node', 'comment_count')\r
+\r
+        print "# Deleting field 'Node.offensive_flag_count'"\r
+        db.delete_column('forum_node', 'offensive_flag_count')\r
+\r
+        print "# Deleting field 'Node.vote_down_count'"\r
+        db.delete_column('forum_node', 'vote_down_count')\r
+\r
+        print "# Adding field 'Node.wiki'"\r
+        db.add_column('forum_node', 'wiki', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True), keep_default=False)\r
+\r
+        print "# Adding field 'Node.marked'"\r
+        db.add_column('forum_node', 'marked', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True), keep_default=False)\r
+\r
+        print "# Adding field 'Node.extra_count'"\r
+        db.add_column('forum_node', 'extra_count', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)\r
+\r
+        print "# Adding field 'Node.last_activity_by'"\r
+        db.add_column('forum_node', 'last_activity_by', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.User'], null=True), keep_default=False)\r
+\r
+        print "# Adding field 'Node.extra_ref'"\r
+        db.add_column('forum_node', 'extra_ref', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.Node'], null=True), keep_default=False)\r
+\r
+        print "# Adding field 'Node.last_activity_at'"\r
+        db.add_column('forum_node', 'last_activity_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True), keep_default=False)\r
+\r
+        # Changing field 'Answer.node_ptr'\r
+        #db.alter_column(u'answer', 'node_ptr_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.Node'], null=True, primary_key=True))\r
+\r
+        print "# Changing field 'QuestionSubscription.question'"\r
+        db.alter_column('forum_questionsubscription', 'question_id', self.gf('django.db.models.fields.IntegerField')())\r
+\r
+        # Removing unique constraint on 'Award', fields ['badge', 'object_id', 'content_type', 'user']\r
+        #db.delete_unique(u'award', ['badge_id', 'object_id', 'content_type_id', 'user_id'])\r
+\r
+        print "# Changing field 'User.gold'"\r
+        db.alter_column('forum_user', 'gold', self.gf('django.db.models.fields.PositiveIntegerField')())\r
+\r
+        print "# Changing field 'User.silver'"\r
+        db.alter_column('forum_user', 'silver', self.gf('django.db.models.fields.PositiveIntegerField')())\r
+\r
+        print "# Changing field 'User.bronze'"\r
+        db.alter_column('forum_user', 'bronze', self.gf('django.db.models.fields.PositiveIntegerField')())\r
+\r
+        print "# Deleting field 'Question.answer_count'"\r
+        db.delete_column(u'question', 'answer_count')\r
+\r
+        print "# Deleting field 'Question.favourite_count'"\r
+        db.delete_column(u'question', 'favourite_count')\r
+\r
+        # Changing field 'Question.node_ptr'\r
+        #db.alter_column(u'question', 'node_ptr_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.Node'], null=True, primary_key=True))\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        \r
+        # Deleting model 'ActionRepute'\r
+        db.delete_table('forum_actionrepute')\r
+\r
+        # Deleting model 'Action'\r
+        db.delete_table('forum_action')\r
+\r
+        # Deleting model 'FavoriteNode'\r
+        db.delete_table('forum_favoritenode')\r
+\r
+        # Adding field 'Node.vote_up_count'\r
+        db.add_column('forum_node', 'vote_up_count', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)\r
+\r
+        # Adding field 'Node.comment_count'\r
+        db.add_column('forum_node', 'comment_count', self.gf('django.db.models.fields.PositiveIntegerField')(default=0), keep_default=False)\r
+\r
+        # Adding field 'Node.offensive_flag_count'\r
+        db.add_column('forum_node', 'offensive_flag_count', self.gf('django.db.models.fields.SmallIntegerField')(default=0), keep_default=False)\r
+\r
+        # Adding field 'Node.vote_down_count'\r
+        db.add_column('forum_node', 'vote_down_count', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)\r
+\r
+        # Deleting field 'Node.wiki'\r
+        db.delete_column('forum_node', 'wiki')\r
+\r
+        # Deleting field 'Node.marked'\r
+        db.delete_column('forum_node', 'marked')\r
+\r
+        # Deleting field 'Node.extra_count'\r
+        db.delete_column('forum_node', 'extra_count')\r
+\r
+        # Deleting field 'Node.last_activity_by'\r
+        db.delete_column('forum_node', 'last_activity_by_id')\r
+\r
+        # Deleting field 'Node.extra_ref'\r
+        db.delete_column('forum_node', 'extra_ref_id')\r
+\r
+        # Deleting field 'Node.last_activity_at'\r
+        db.delete_column('forum_node', 'last_activity_at')\r
+\r
+        # Changing field 'Answer.node_ptr'\r
+        db.alter_column(u'answer', 'node_ptr_id', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['forum.Node'], unique=True, primary_key=True))\r
+\r
+        # Adding unique constraint on 'Award', fields ['badge', 'object_id', 'content_type', 'user']\r
+        db.create_unique(u'award', ['badge_id', 'object_id', 'content_type_id', 'user_id'])\r
+\r
+        # Changing field 'User.gold'\r
+        db.alter_column('forum_user', 'gold', self.gf('django.db.models.fields.SmallIntegerField')())\r
+\r
+        # Changing field 'User.silver'\r
+        db.alter_column('forum_user', 'silver', self.gf('django.db.models.fields.SmallIntegerField')())\r
+\r
+        # Changing field 'User.bronze'\r
+        db.alter_column('forum_user', 'bronze', self.gf('django.db.models.fields.SmallIntegerField')())\r
+\r
+        # Adding field 'Question.answer_count'\r
+        db.add_column(u'question', 'answer_count', self.gf('django.db.models.fields.PositiveIntegerField')(default=0), keep_default=False)\r
+\r
+        # Adding field 'Question.favourite_count'\r
+        db.add_column(u'question', 'favourite_count', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)\r
+\r
+        # Changing field 'Question.node_ptr'\r
+        db.alter_column(u'question', 'node_ptr_id', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['forum.Node'], unique=True))\r
+    \r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.action': {\r
+            'Meta': {'object_name': 'Action'},\r
+            'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),\r
+            'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'extra': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.actionrepute': {\r
+            'Meta': {'object_name': 'ActionRepute'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}),\r
+            'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.anonymousnode': {\r
+            'Meta': {'object_name': 'AnonymousNode', '_ormbases': ['forum.Node']},\r
+            'convertible_to': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'validation_hash': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_content'", 'to': "orm['forum.Node']"})\r
+        },\r
+        'forum.answer': {\r
+            'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"},\r
+            'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'accepted_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'node_ptr': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True', 'primary_key': 'True'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.favoritequestion': {\r
+            'Meta': {'unique_together': "(('question', 'user'),)", 'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'favourites'", 'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.flaggeditem': {\r
+            'Meta': {'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.openidassociation': {\r
+            'Meta': {'object_name': 'OpenIdAssociation'},\r
+            'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}),\r
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'issued': ('django.db.models.fields.IntegerField', [], {}),\r
+            'lifetime': ('django.db.models.fields.IntegerField', [], {}),\r
+            'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}),\r
+            'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'})\r
+        },\r
+        'forum.openidnonce': {\r
+            'Meta': {'object_name': 'OpenIdNonce'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),\r
+            'timestamp': ('django.db.models.fields.IntegerField', [], {})\r
+        },\r
+        'forum.question': {\r
+            'Meta': {'object_name': 'Question', 'db_table': "u'question'"},\r
+            'accepted_answer': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'question_accepting'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Answer']"}),\r
+            'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['forum.User']"}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_ptr': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True', 'primary_key': 'True'}),\r
+            'view_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 27, 11, 37, 29, 356000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.repute': {\r
+            'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'user_previous_rep': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 28, 11, 37, 29, 624000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'object_name': 'Vote', 'db_table': "u'vote'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'vote': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0023_flaten_node_inheritance_create_actions.py b/forum/modules/template_loader.py/forum/migrations/0023_flaten_node_inheritance_create_actions.py
new file mode 100644 (file)
index 0000000..d4b081b
--- /dev/null
@@ -0,0 +1,685 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import DataMigration\r
+from django.db import models\r
+from forum.migrations import ProgressBar\r
+\r
+GAIN_BY_UPVOTED = 1\r
+GAIN_BY_ANSWER_ACCEPTED = 2\r
+GAIN_BY_ACCEPTING_ANSWER = 3\r
+GAIN_BY_DOWNVOTE_CANCELED = 4\r
+GAIN_BY_CANCELING_DOWNVOTE = 5\r
+LOST_BY_CANCELLING_ACCEPTED_ANSWER = -1\r
+LOST_BY_ACCEPTED_ANSWER_CANCELED = -2\r
+LOST_BY_DOWNVOTED = -3\r
+LOST_BY_FLAGGED = -4\r
+LOST_BY_DOWNVOTING = -5\r
+LOST_BY_FLAGGED_3_TIMES = -6\r
+LOST_BY_FLAGGED_5_TIMES = -7\r
+LOST_BY_UPVOTE_CANCELED = -8\r
+\r
+class Migration(DataMigration):\r
+    \r
+    def forwards(self, orm):\r
+        rephist = dict([(t, []) for t in range(-8, 6) if t != 0])\r
+\r
+        r_count = orm.Repute.objects.count()\r
+        print "\nCalculating rep gain/losses history through %d records:" % r_count\r
+        progress = ProgressBar(r_count)\r
+\r
+        for r in orm.Repute.objects.all():\r
+            l = rephist.get(r.reputation_type, None)\r
+            if l is None: continue\r
+\r
+            if (len(l) == 0) or (l[-1][1] != r.value):\r
+                l.append((r.reputed_at, r.value))\r
+\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+\r
+\r
+        def repval_at(reptype, repdate, default):\r
+            l = rephist.get(reptype, None)\r
+\r
+            if l is None: return 0\r
+            if len(l) == 0: return default\r
+\r
+            for r in l:\r
+                if r[0] <= repdate:\r
+                    return r[1] or default\r
+\r
+\r
+        q_count = orm.Question.objects.count()\r
+        print "\nConverting %d questions:" % q_count\r
+        progress = ProgressBar(q_count)\r
+\r
+        for q in orm.Question.objects.all():\r
+            n = q.node_ptr\r
+            n.last_activity_at = q.last_activity_at\r
+            n.last_activity_by = q.last_activity_by\r
+\r
+            if q.accepted_answer:\r
+                n.extra_ref = q.accepted_answer.node_ptr\r
+                \r
+            n.extra_count = q.view_count\r
+\r
+            n.marked = q.closed\r
+            n.wiki = q.wiki\r
+\r
+            n.save()\r
+\r
+            ask = orm.Action(\r
+                user = n.author,\r
+                action_date = n.added_at,\r
+                node = n,\r
+                action_type = "ask",\r
+                extra = ''\r
+            )\r
+\r
+            ask.save()\r
+\r
+            if n.deleted:\r
+                action = orm.Action(\r
+                    user = n.deleted_by,\r
+                    node = n,\r
+                    action_type = "delete",\r
+                    action_date = n.deleted_at or datetime.datetime.now(),\r
+                    extra = ''\r
+                )\r
+\r
+                action.save()\r
+\r
+\r
+            if n.marked:\r
+                action = orm.Action(\r
+                    user = q.closed_by,\r
+                    node = n,\r
+                    action_type = "close",\r
+                    extra = q.close_reason,\r
+                    action_date = q.closed_at or datetime.datetime.now(),\r
+                )\r
+\r
+                action.save()\r
+\r
+            if n.wiki:\r
+                action = orm.Action(\r
+                    user = n.author,\r
+                    node = n,\r
+                    action_type = "wikify",\r
+                    action_date = q.wikified_at or datetime.datetime.now(),\r
+                    extra = ''\r
+                )\r
+\r
+                action.save()\r
+\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+\r
+        a_count = orm.Answer.objects.count()\r
+        print "\nConverting %d answers:" % a_count\r
+        progress = ProgressBar(a_count)\r
+\r
+        for a in orm.Answer.objects.all():\r
+            n = a.node_ptr\r
+\r
+            n.marked = a.accepted\r
+            n.wiki = a.wiki\r
+\r
+            n.save()\r
+\r
+            ans = orm.Action(\r
+                user = n.author,\r
+                action_date = n.added_at,\r
+                node = n,\r
+                action_type = "answer",\r
+                extra = ''\r
+            )\r
+\r
+            ans.save()\r
+\r
+            if n.deleted:\r
+                action = orm.Action(\r
+                    user = n.deleted_by,\r
+                    node = n,\r
+                    action_type = "delete",\r
+                    action_date = n.deleted_at or datetime.datetime.now(),\r
+                    extra = ''\r
+                )\r
+\r
+                action.save()\r
+\r
+            if a.accepted:\r
+                action = orm.Action(\r
+                    user = a.accepted_by,\r
+                    node = n,\r
+                    action_type = "acceptanswer",\r
+                    action_date = a.accepted_at or datetime.datetime.now(),\r
+                    extra = ''\r
+                )\r
+\r
+                action.save()\r
+\r
+                if not a.wiki or a.wikified_at > action.action_date:\r
+                    if action.user == n.author:\r
+                        rep = orm.ActionRepute(\r
+                            action = action,\r
+                            user = action.user,\r
+                            value = repval_at(GAIN_BY_ACCEPTING_ANSWER, action.action_date, 2)\r
+                        )\r
+                        rep.save()\r
+\r
+                    if n.author != n.parent.author:\r
+                        rep = orm.ActionRepute(\r
+                            action = action,\r
+                            user = n.author,\r
+                            value = repval_at(GAIN_BY_ANSWER_ACCEPTED, action.action_date, 15)\r
+                        )\r
+                        rep.save()\r
+\r
+            if n.wiki:\r
+                action = orm.Action(\r
+                    user = n.author,\r
+                    node = n,\r
+                    action_type = "wikify",\r
+                    action_date = a.wikified_at or datetime.datetime.now(),\r
+                    extra = ''\r
+                )\r
+\r
+                action.save()\r
+\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+\r
+        v_count = orm.Vote.objects.count()\r
+        print "\nConverting %d votes:" % v_count\r
+        progress = ProgressBar(v_count)\r
+\r
+        for v in orm.Vote.objects.exclude(canceled=True):\r
+            a = orm.Action(\r
+                action_type = (v.vote == 1) and ((v.node.node_type == "comment") and "voteupcomment" or "voteup") or "votedown",\r
+                user = v.user,\r
+                node = v.node,\r
+                action_date = v.voted_at,\r
+                canceled = v.canceled,\r
+                extra = ''\r
+            )\r
+\r
+            a.save()\r
+\r
+            def impl(node):\r
+                if node.node_type == "question":\r
+                    return orm.Question.objects.get(node_ptr=node)\r
+                else:\r
+                    return orm.Answer.objects.get(node_ptr=node)\r
+\r
+            if a.node.node_type in ("question", "answer") and (not a.node.wiki or impl(a.node).wikified_at > a.action_date):\r
+                reptype, default = (v.vote == 1) and (GAIN_BY_UPVOTED, 10) or (LOST_BY_DOWNVOTED, 2)\r
+                rep = orm.ActionRepute(\r
+                    action = a,\r
+                    user = a.node.author,\r
+                    value = repval_at(reptype, a.action_date, default) or default\r
+                )\r
+                rep.save()\r
+\r
+                if v.vote == -1:\r
+                    rep = orm.ActionRepute(\r
+                        action = a,\r
+                        user = a.node.author,\r
+                        value = repval_at(LOST_BY_DOWNVOTING, a.action_date, 1) or default\r
+                    )\r
+                    rep.save()\r
+\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+\r
+        f_count = orm.FlaggedItem.objects.count()\r
+        print "\nConverting %d flags:" % f_count\r
+        progress = ProgressBar(f_count)\r
+\r
+        for f in orm.FlaggedItem.objects.all():\r
+            a = orm.Action(\r
+                action_type = "flag",\r
+                user = f.user,\r
+                node = f.node,\r
+                action_date = f.flagged_at,\r
+                extra = f.reason or ''\r
+            )\r
+\r
+            a.save()\r
+\r
+            rep = orm.ActionRepute(\r
+                action = a,\r
+                user = a.node.author,\r
+                value = repval_at(LOST_BY_FLAGGED, a.action_date, 2) or 2\r
+            )\r
+            rep.save()\r
+\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+\r
+        n_count = orm.Node.objects.all().count()\r
+        print "\nChecking flag count of %d nodes:" % n_count\r
+        progress = ProgressBar(n_count)\r
+\r
+        for n in orm.Node.objects.all():\r
+            flags = list(orm.Action.objects.filter(action_type="flag", node=n, canceled=False).order_by('-action_date'))\r
+\r
+            if len(flags) >= 3:\r
+                a = flags[2]\r
+                rep = orm.ActionRepute(\r
+                    action = a,\r
+                    user = n.author,\r
+                    value = repval_at(LOST_BY_FLAGGED_3_TIMES, a.action_date, 30)\r
+                )\r
+                rep.save()\r
+\r
+\r
+            if len(flags) >= 5:\r
+                a = flags[4]\r
+                rep = orm.ActionRepute(\r
+                    action = a,\r
+                    user = n.author,\r
+                    value = repval_at(LOST_BY_FLAGGED_5_TIMES, a.action_date, 100)\r
+                )\r
+                rep.save()\r
+\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+\r
+        c_count = orm.Node.objects.filter(node_type="comment").count()\r
+        print "\nCreating %d comment actions:" % c_count\r
+        progress = ProgressBar(c_count)\r
+\r
+        for c in orm.Node.objects.filter(node_type="comment").all():\r
+            a = orm.Action(\r
+                action_type = "comment",\r
+                user = c.author,\r
+                node = c,\r
+                action_date = c.added_at,\r
+                extra = ''\r
+            )\r
+\r
+            a.save()\r
+\r
+            if c.deleted:\r
+                action = orm.Action(\r
+                    user = c.deleted_by,\r
+                    node = c,\r
+                    action_type = "delete",\r
+                    action_date = c.deleted_at or datetime.datetime.now(),\r
+                    extra = ''\r
+                )\r
+\r
+                action.save()\r
+\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+\r
+\r
+        r_count = orm.NodeRevision.objects.exclude(revision=1).count()\r
+        print "\nCreating %d edit actions:" % r_count\r
+        progress = ProgressBar(r_count)\r
+\r
+        for r in orm.NodeRevision.objects.exclude(revision=1):\r
+            a = orm.Action(\r
+                action_type = "revise",\r
+                user = r.author,\r
+                node = r.node,\r
+                action_date = r.revised_at,\r
+                extra = r.revision\r
+            )\r
+\r
+            a.save()\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+\r
+        u_count = orm.User.objects.all().count()\r
+        print "\nCreating %d user join actions and reputation recalculation:" % u_count\r
+        progress = ProgressBar(u_count)\r
+\r
+        for u in orm.User.objects.all():\r
+            a = orm.Action(\r
+                user = u,\r
+                action_date = u.date_joined,\r
+                action_type = "userjoins",\r
+            )\r
+\r
+            a.save()\r
+\r
+            rep = orm.ActionRepute(\r
+                action = a,\r
+                user = u,\r
+                value = 1\r
+            )\r
+            rep.save()\r
+\r
+            new_rep = orm.ActionRepute.objects.filter(user=u).aggregate(reputation=models.Sum('value'))['reputation']\r
+\r
+            if new_rep < 0:\r
+                new_rep = 1\r
+\r
+            u.reputation = new_rep\r
+            u.save()\r
+\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        "Write your backwards methods here."\r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.action': {\r
+            'Meta': {'object_name': 'Action'},\r
+            'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),\r
+            'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'extra': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.actionrepute': {\r
+            'Meta': {'object_name': 'ActionRepute'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}),\r
+            'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.anonymousnode': {\r
+            'Meta': {'object_name': 'AnonymousNode', '_ormbases': ['forum.Node']},\r
+            'convertible_to': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'validation_hash': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_content'", 'to': "orm['forum.Node']"})\r
+        },\r
+        'forum.answer': {\r
+            'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"},\r
+            'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'accepted_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'node_ptr': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True', 'primary_key': 'True'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.favoritequestion': {\r
+            'Meta': {'unique_together': "(('question', 'user'),)", 'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'favourites'", 'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.flaggeditem': {\r
+            'Meta': {'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.openidassociation': {\r
+            'Meta': {'object_name': 'OpenIdAssociation'},\r
+            'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}),\r
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'issued': ('django.db.models.fields.IntegerField', [], {}),\r
+            'lifetime': ('django.db.models.fields.IntegerField', [], {}),\r
+            'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}),\r
+            'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'})\r
+        },\r
+        'forum.openidnonce': {\r
+            'Meta': {'object_name': 'OpenIdNonce'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),\r
+            'timestamp': ('django.db.models.fields.IntegerField', [], {})\r
+        },\r
+        'forum.question': {\r
+            'Meta': {'object_name': 'Question', 'db_table': "u'question'"},\r
+            'accepted_answer': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'question_accepting'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Answer']"}),\r
+            'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['forum.User']"}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_ptr': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True', 'primary_key': 'True'}),\r
+            'view_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 27, 11, 40, 32, 68000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.repute': {\r
+            'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'user_previous_rep': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 28, 11, 40, 32, 153000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'object_name': 'Vote', 'db_table': "u'vote'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'vote': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0024_auto__del_repute__del_vote__del_answer__del_flaggeditem__del_anonymous.py b/forum/modules/template_loader.py/forum/migrations/0024_auto__del_repute__del_vote__del_answer__del_flaggeditem__del_anonymous.py
new file mode 100644 (file)
index 0000000..38a7604
--- /dev/null
@@ -0,0 +1,377 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import SchemaMigration\r
+from django.db import models\r
+\r
+class Migration(SchemaMigration):\r
+    \r
+    def forwards(self, orm):\r
+        \r
+        # Deleting model 'Repute'\r
+        db.delete_table(u'repute')\r
+\r
+        # Deleting model 'Vote'\r
+        db.delete_table(u'vote')\r
+\r
+        # Deleting model 'Answer'\r
+        db.delete_table(u'answer')\r
+\r
+        # Deleting model 'FlaggedItem'\r
+        db.delete_table(u'flagged_item')\r
+\r
+        # Deleting model 'AnonymousNode'\r
+        db.delete_table('forum_anonymousnode')\r
+\r
+        # Deleting model 'FavoriteQuestion'\r
+        db.delete_table(u'favorite_question')\r
+\r
+        # Deleting model 'Question'\r
+        db.delete_table(u'question')\r
+\r
+        # Deleting field 'Node.deleted_at'\r
+        db.delete_column('forum_node', 'deleted_at')\r
+\r
+        # Deleting field 'Node.last_edited_by'\r
+        db.delete_column('forum_node', 'last_edited_by_id')\r
+\r
+        # Deleting field 'Node.deleted'\r
+        db.delete_column('forum_node', 'deleted')\r
+\r
+        # Deleting field 'Node.deleted_by'\r
+        db.delete_column('forum_node', 'deleted_by_id')\r
+\r
+        # Deleting field 'Node.last_edited_at'\r
+        db.delete_column('forum_node', 'last_edited_at')\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        \r
+        # Adding model 'Repute'\r
+        db.create_table(u'repute', (\r
+            ('node', self.gf('django.db.models.fields.related.ForeignKey')(related_name='reputes', null=True, to=orm['forum.Node'])),\r
+            ('reputed_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+            ('question', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.Question'])),\r
+            ('value', self.gf('django.db.models.fields.SmallIntegerField')(default=0)),\r
+            ('canceled', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('reputation_type', self.gf('django.db.models.fields.SmallIntegerField')()),\r
+            ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='reputes', to=orm['forum.User'])),\r
+            ('user_previous_rep', self.gf('django.db.models.fields.IntegerField')(default=0)),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+        ))\r
+        db.send_create_signal('forum', ['Repute'])\r
+\r
+        # Adding model 'Vote'\r
+        db.create_table(u'vote', (\r
+            ('node', self.gf('django.db.models.fields.related.ForeignKey')(related_name='votes', null=True, to=orm['forum.Node'])),\r
+            ('vote', self.gf('django.db.models.fields.SmallIntegerField')()),\r
+            ('canceled', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='votes', to=orm['forum.User'])),\r
+            ('voted_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+        ))\r
+        db.send_create_signal('forum', ['Vote'])\r
+\r
+        # Adding model 'Answer'\r
+        db.create_table(u'answer', (\r
+            ('wiki', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('accepted_by', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.User'], null=True)),\r
+            ('accepted_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),\r
+            ('wikified_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),\r
+            ('node_ptr', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.Node'], null=True, primary_key=True)),\r
+            ('accepted', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+        ))\r
+        db.send_create_signal('forum', ['Answer'])\r
+\r
+        # Adding model 'FlaggedItem'\r
+        db.create_table(u'flagged_item', (\r
+            ('node', self.gf('django.db.models.fields.related.ForeignKey')(related_name='flaggeditems', null=True, to=orm['forum.Node'])),\r
+            ('flagged_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+            ('canceled', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('reason', self.gf('django.db.models.fields.CharField')(max_length=300, null=True)),\r
+            ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='flaggeditems', to=orm['forum.User'])),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+        ))\r
+        db.send_create_signal('forum', ['FlaggedItem'])\r
+\r
+        # Adding model 'AnonymousNode'\r
+        db.create_table('forum_anonymousnode', (\r
+            ('convertible_to', self.gf('django.db.models.fields.CharField')(default='node', max_length=16)),\r
+            ('validation_hash', self.gf('django.db.models.fields.related.ForeignKey')(related_name='anonymous_content', to=orm['forum.Node'])),\r
+            ('node_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['forum.Node'], unique=True, primary_key=True)),\r
+        ))\r
+        db.send_create_signal('forum', ['AnonymousNode'])\r
+\r
+        # Adding model 'FavoriteQuestion'\r
+        db.create_table(u'favorite_question', (\r
+            ('question', self.gf('django.db.models.fields.related.ForeignKey')(related_name='favourites', to=orm['forum.Question'])),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('added_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+            ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='user_favorite_questions', to=orm['forum.User'])),\r
+        ))\r
+        db.send_create_signal('forum', ['FavoriteQuestion'])\r
+\r
+        # Adding model 'Question'\r
+        db.create_table(u'question', (\r
+            ('wiki', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('last_activity_by', self.gf('django.db.models.fields.related.ForeignKey')(related_name='last_active_in_questions', null=True, to=orm['forum.User'])),\r
+            ('close_reason', self.gf('django.db.models.fields.SmallIntegerField')(null=True, blank=True)),\r
+            ('last_activity_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+            ('view_count', self.gf('django.db.models.fields.IntegerField')(default=0)),\r
+            ('node_ptr', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.Node'], null=True, primary_key=True)),\r
+            ('accepted_answer', self.gf('django.db.models.fields.related.OneToOneField')(related_name='question_accepting', unique=True, null=True, to=orm['forum.Answer'])),\r
+            ('closed', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('wikified_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),\r
+            ('closed_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),\r
+            ('closed_by', self.gf('django.db.models.fields.related.ForeignKey')(related_name='closed_questions', null=True, to=orm['forum.User'], blank=True)),\r
+        ))\r
+        db.send_create_signal('forum', ['Question'])\r
+\r
+        # Adding field 'Node.deleted_at'\r
+        db.add_column('forum_node', 'deleted_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True), keep_default=False)\r
+\r
+        # Adding field 'Node.last_edited_by'\r
+        db.add_column('forum_node', 'last_edited_by', self.gf('django.db.models.fields.related.ForeignKey')(related_name='last_edited_nodes', null=True, to=orm['forum.User'], blank=True), keep_default=False)\r
+\r
+        # Adding field 'Node.deleted'\r
+        db.add_column('forum_node', 'deleted', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True), keep_default=False)\r
+\r
+        # Adding field 'Node.deleted_by'\r
+        db.add_column('forum_node', 'deleted_by', self.gf('django.db.models.fields.related.ForeignKey')(related_name='deleted_nodes', null=True, to=orm['forum.User'], blank=True), keep_default=False)\r
+\r
+        # Adding field 'Node.last_edited_at'\r
+        db.add_column('forum_node', 'last_edited_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True), keep_default=False)\r
+    \r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.action': {\r
+            'Meta': {'object_name': 'Action'},\r
+            'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),\r
+            'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'extra': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.actionrepute': {\r
+            'Meta': {'object_name': 'ActionRepute'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}),\r
+            'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.openidassociation': {\r
+            'Meta': {'object_name': 'OpenIdAssociation'},\r
+            'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}),\r
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'issued': ('django.db.models.fields.IntegerField', [], {}),\r
+            'lifetime': ('django.db.models.fields.IntegerField', [], {}),\r
+            'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}),\r
+            'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'})\r
+        },\r
+        'forum.openidnonce': {\r
+            'Meta': {'object_name': 'OpenIdNonce'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),\r
+            'timestamp': ('django.db.models.fields.IntegerField', [], {})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 28, 23, 43, 52, 301000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 29, 23, 43, 52, 512000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0025_auto__add_field_node_extra_action__add_field_node_deleted__add_field_n.py b/forum/modules/template_loader.py/forum/migrations/0025_auto__add_field_node_extra_action__add_field_node_deleted__add_field_n.py
new file mode 100644 (file)
index 0000000..2cf638c
--- /dev/null
@@ -0,0 +1,267 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import SchemaMigration\r
+from django.db import models\r
+\r
+class Migration(SchemaMigration):\r
+    \r
+    def forwards(self, orm):\r
+        \r
+        # Adding field 'Node.extra_action'\r
+        db.add_column('forum_node', 'extra_action', self.gf('django.db.models.fields.related.ForeignKey')(related_name='extra_node', null=True, to=orm['forum.Action']), keep_default=False)\r
+\r
+        # Adding field 'Node.deleted'\r
+        db.add_column('forum_node', 'deleted', self.gf('django.db.models.fields.related.ForeignKey')(related_name='deleted_node', unique=True, null=True, to=orm['forum.Action']), keep_default=False)\r
+\r
+        # Adding field 'Node.last_edited'\r
+        db.add_column('forum_node', 'last_edited', self.gf('django.db.models.fields.related.ForeignKey')(related_name='edited_node', unique=True, null=True, to=orm['forum.Action']), keep_default=False)\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        \r
+        # Deleting field 'Node.extra_action'\r
+        db.delete_column('forum_node', 'extra_action_id')\r
+\r
+        # Deleting field 'Node.deleted'\r
+        db.delete_column('forum_node', 'deleted_id')\r
+\r
+        # Deleting field 'Node.last_edited'\r
+        db.delete_column('forum_node', 'last_edited_id')\r
+    \r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.action': {\r
+            'Meta': {'object_name': 'Action'},\r
+            'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),\r
+            'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'extra': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.actionrepute': {\r
+            'Meta': {'object_name': 'ActionRepute'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}),\r
+            'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'deleted': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'deleted_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'extra_action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'extra_node'", 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.openidassociation': {\r
+            'Meta': {'object_name': 'OpenIdAssociation'},\r
+            'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}),\r
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'issued': ('django.db.models.fields.IntegerField', [], {}),\r
+            'lifetime': ('django.db.models.fields.IntegerField', [], {}),\r
+            'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}),\r
+            'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'})\r
+        },\r
+        'forum.openidnonce': {\r
+            'Meta': {'object_name': 'OpenIdNonce'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),\r
+            'timestamp': ('django.db.models.fields.IntegerField', [], {})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 28, 23, 49, 37, 322000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 29, 23, 49, 37, 506000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0026_reset_deleted_and_lastedited_flags.py b/forum/modules/template_loader.py/forum/migrations/0026_reset_deleted_and_lastedited_flags.py
new file mode 100644 (file)
index 0000000..8521ffd
--- /dev/null
@@ -0,0 +1,278 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import DataMigration\r
+from django.db import models\r
+from forum.migrations import ProgressBar\r
+\r
+class Migration(DataMigration):\r
+    \r
+    def forwards(self, orm):\r
+        n_count = orm.Node.objects.all().count()\r
+        print "\nReseting %d nodes:" % n_count\r
+        progress = ProgressBar(n_count)\r
+\r
+        for n in orm.Node.objects.all():\r
+            try:\r
+                d = orm.Action.objects.get(node=n, action_type="delete", canceled=False)\r
+                n.deleted_id = d.id\r
+            except Exception, e:\r
+                n.deleted = None\r
+\r
+            if orm.Action.objects.filter(node=n, action_type="revise").count() > 0:\r
+                n.last_edited_id = orm.Action.objects.filter(node=n, action_type="revise").order_by('-action_date')[0].id\r
+            else:\r
+                n.last_edited = None\r
+\r
+\r
+            if n.node_type == "answer" and n.marked:\r
+                n.extra_action_id = orm.Action.objects.get(node=n, action_type="acceptanswer", canceled=False).id\r
+\r
+            if n.node_type == "question" and n.marked:\r
+                n.extra_action_id = orm.Action.objects.get(node=n, action_type="close", canceled=False).id\r
+\r
+            n.save()\r
+\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        "Write your backwards methods here."\r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.action': {\r
+            'Meta': {'object_name': 'Action'},\r
+            'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),\r
+            'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'extra': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.actionrepute': {\r
+            'Meta': {'object_name': 'ActionRepute'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}),\r
+            'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'deleted': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'deleted_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'extra_action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'extra_node'", 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.openidassociation': {\r
+            'Meta': {'object_name': 'OpenIdAssociation'},\r
+            'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}),\r
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'issued': ('django.db.models.fields.IntegerField', [], {}),\r
+            'lifetime': ('django.db.models.fields.IntegerField', [], {}),\r
+            'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}),\r
+            'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'})\r
+        },\r
+        'forum.openidnonce': {\r
+            'Meta': {'object_name': 'OpenIdNonce'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),\r
+            'timestamp': ('django.db.models.fields.IntegerField', [], {})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 28, 23, 55, 36, 647000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 29, 23, 55, 36, 708000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0027_auto__del_activity.py b/forum/modules/template_loader.py/forum/migrations/0027_auto__del_activity.py
new file mode 100644 (file)
index 0000000..589b5bb
--- /dev/null
@@ -0,0 +1,254 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import SchemaMigration\r
+from django.db import models\r
+\r
+class Migration(SchemaMigration):\r
+    \r
+    def forwards(self, orm):\r
+        \r
+        # Deleting model 'Activity'\r
+        db.delete_table(u'activity')\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        \r
+        # Adding model 'Activity'\r
+        db.create_table(u'activity', (\r
+            ('is_auditted', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),\r
+            ('object_id', self.gf('django.db.models.fields.PositiveIntegerField')()),\r
+            ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.User'])),\r
+            ('content_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['contenttypes.ContentType'])),\r
+            ('active_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('activity_type', self.gf('django.db.models.fields.SmallIntegerField')()),\r
+        ))\r
+        db.send_create_signal('forum', ['Activity'])\r
+    \r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.action': {\r
+            'Meta': {'object_name': 'Action'},\r
+            'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),\r
+            'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'extra': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.actionrepute': {\r
+            'Meta': {'object_name': 'ActionRepute'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}),\r
+            'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'deleted': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'deleted_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'extra_action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'extra_node'", 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.openidassociation': {\r
+            'Meta': {'object_name': 'OpenIdAssociation'},\r
+            'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}),\r
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'issued': ('django.db.models.fields.IntegerField', [], {}),\r
+            'lifetime': ('django.db.models.fields.IntegerField', [], {}),\r
+            'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}),\r
+            'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'})\r
+        },\r
+        'forum.openidnonce': {\r
+            'Meta': {'object_name': 'OpenIdNonce'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),\r
+            'timestamp': ('django.db.models.fields.IntegerField', [], {})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 29, 1, 30, 30, 35000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 30, 1, 30, 30, 211000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0028_auto__add_field_action_canceled_ip__add_field_actionrepute_date.py b/forum/modules/template_loader.py/forum/migrations/0028_auto__add_field_action_canceled_ip__add_field_actionrepute_date.py
new file mode 100644 (file)
index 0000000..1170bf7
--- /dev/null
@@ -0,0 +1,253 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import SchemaMigration\r
+from django.db import models\r
+\r
+class Migration(SchemaMigration):\r
+    \r
+    def forwards(self, orm):\r
+        \r
+        # Adding field 'Action.canceled_ip'\r
+        db.add_column('forum_action', 'canceled_ip', self.gf('django.db.models.fields.CharField')(default='', max_length=16), keep_default=False)\r
+\r
+        # Adding field 'ActionRepute.date'\r
+        db.add_column('forum_actionrepute', 'date', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now), keep_default=False)\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        \r
+        # Deleting field 'Action.canceled_ip'\r
+        db.delete_column('forum_action', 'canceled_ip')\r
+\r
+        # Deleting field 'ActionRepute.date'\r
+        db.delete_column('forum_actionrepute', 'date')\r
+    \r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.action': {\r
+            'Meta': {'object_name': 'Action'},\r
+            'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),\r
+            'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'extra': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.actionrepute': {\r
+            'Meta': {'object_name': 'ActionRepute'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}),\r
+            'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'deleted': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'deleted_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'extra_action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'extra_node'", 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.openidassociation': {\r
+            'Meta': {'object_name': 'OpenIdAssociation'},\r
+            'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}),\r
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'issued': ('django.db.models.fields.IntegerField', [], {}),\r
+            'lifetime': ('django.db.models.fields.IntegerField', [], {}),\r
+            'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}),\r
+            'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'})\r
+        },\r
+        'forum.openidnonce': {\r
+            'Meta': {'object_name': 'OpenIdNonce'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),\r
+            'timestamp': ('django.db.models.fields.IntegerField', [], {})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 29, 21, 20, 24, 880000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 30, 21, 20, 35, 361000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0029_repute_dates.py b/forum/modules/template_loader.py/forum/migrations/0029_repute_dates.py
new file mode 100644 (file)
index 0000000..14d6e62
--- /dev/null
@@ -0,0 +1,259 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import DataMigration\r
+from django.db import models\r
+from forum.migrations import ProgressBar\r
+\r
+class Migration(DataMigration):\r
+    \r
+    def forwards(self, orm):\r
+        r_count = orm.ActionRepute.objects.count()\r
+        print "\nAdding dates to %d repute actions:" % r_count\r
+        progress = ProgressBar(r_count)\r
+\r
+        for r in orm.ActionRepute.objects.all():\r
+            a = r.action\r
+\r
+            if r.by_canceled:\r
+                r.date = a.canceled_at\r
+            else:\r
+                r.date = a.action_date\r
+\r
+            r.save()\r
+\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        "Write your backwards methods here."\r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.action': {\r
+            'Meta': {'object_name': 'Action'},\r
+            'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),\r
+            'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'extra': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.actionrepute': {\r
+            'Meta': {'object_name': 'ActionRepute'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}),\r
+            'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'deleted': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'deleted_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'extra_action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'extra_node'", 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.openidassociation': {\r
+            'Meta': {'object_name': 'OpenIdAssociation'},\r
+            'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}),\r
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'issued': ('django.db.models.fields.IntegerField', [], {}),\r
+            'lifetime': ('django.db.models.fields.IntegerField', [], {}),\r
+            'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}),\r
+            'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'})\r
+        },\r
+        'forum.openidnonce': {\r
+            'Meta': {'object_name': 'OpenIdNonce'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),\r
+            'timestamp': ('django.db.models.fields.IntegerField', [], {})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 29, 21, 21, 16, 237000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 30, 21, 21, 16, 298000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0030_auto__chg_field_action_extra__chg_field_keyvalue_value.py b/forum/modules/template_loader.py/forum/migrations/0030_auto__chg_field_action_extra__chg_field_keyvalue_value.py
new file mode 100644 (file)
index 0000000..cd4e1f1
--- /dev/null
@@ -0,0 +1,253 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import SchemaMigration\r
+from django.db import models\r
+\r
+class Migration(SchemaMigration):\r
+    \r
+    def forwards(self, orm):\r
+        \r
+        # Changing field 'Action.extra'\r
+        db.alter_column('forum_action', 'extra', self.gf('forum.models.utils.PickledObjectField')(null=True))\r
+\r
+        # Changing field 'KeyValue.value'\r
+        db.alter_column('forum_keyvalue', 'value', self.gf('forum.models.utils.PickledObjectField')(null=True))\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        \r
+        # Changing field 'Action.extra'\r
+        db.alter_column('forum_action', 'extra', self.gf('django.db.models.fields.CharField')(max_length=255))\r
+\r
+        # Changing field 'KeyValue.value'\r
+        db.alter_column('forum_keyvalue', 'value', self.gf('forum.models.utils.PickledObjectField')())\r
+    \r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.action': {\r
+            'Meta': {'object_name': 'Action'},\r
+            'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),\r
+            'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.actionrepute': {\r
+            'Meta': {'object_name': 'ActionRepute'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}),\r
+            'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'deleted': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'deleted_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'extra_action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'extra_node'", 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.openidassociation': {\r
+            'Meta': {'object_name': 'OpenIdAssociation'},\r
+            'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}),\r
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'issued': ('django.db.models.fields.IntegerField', [], {}),\r
+            'lifetime': ('django.db.models.fields.IntegerField', [], {}),\r
+            'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}),\r
+            'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'})\r
+        },\r
+        'forum.openidnonce': {\r
+            'Meta': {'object_name': 'OpenIdNonce'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),\r
+            'timestamp': ('django.db.models.fields.IntegerField', [], {})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 30, 23, 58, 8, 677000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 1, 23, 58, 8, 841000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0031_alter_pickle_storage.py b/forum/modules/template_loader.py/forum/migrations/0031_alter_pickle_storage.py
new file mode 100644 (file)
index 0000000..5c8bb7b
--- /dev/null
@@ -0,0 +1,274 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import DataMigration\r
+from django.db import models\r
+from forum.migrations import ProgressBar\r
+from forum.models.utils import dbsafe_encode\r
+\r
+try:\r
+    from cPickle import loads, dumps\r
+except ImportError:\r
+    from pickle import loads, dumps\r
+\r
+class Migration(DataMigration):\r
+    \r
+    def forwards(self, orm):\r
+        k_count = orm.KeyValue.objects.count()\r
+        print "\nConverting %d keyvalue objects:" % k_count\r
+        progress = ProgressBar(k_count)\r
+\r
+        for kv in orm.KeyValue.objects.all():\r
+            try:\r
+                o = loads(kv.value.encode('utf-8'))\r
+            except:\r
+                o = kv.value\r
+\r
+            kv.value = dbsafe_encode(o, compress_object=True)\r
+            kv.save()\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+\r
+        a_count = orm.Action.objects.count()\r
+        print "\nConverting %d actions extra fields:" % a_count\r
+        progress = ProgressBar(a_count)\r
+\r
+        for a in orm.Action.objects.all():\r
+            a.extra = dbsafe_encode(a.extra, compress_object=True)\r
+            a.save()\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        "Write your backwards methods here."\r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.action': {\r
+            'Meta': {'object_name': 'Action'},\r
+            'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),\r
+            'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.actionrepute': {\r
+            'Meta': {'object_name': 'ActionRepute'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}),\r
+            'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'deleted': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'deleted_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'extra_action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'extra_node'", 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.openidassociation': {\r
+            'Meta': {'object_name': 'OpenIdAssociation'},\r
+            'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}),\r
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'issued': ('django.db.models.fields.IntegerField', [], {}),\r
+            'lifetime': ('django.db.models.fields.IntegerField', [], {}),\r
+            'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}),\r
+            'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'})\r
+        },\r
+        'forum.openidnonce': {\r
+            'Meta': {'object_name': 'OpenIdNonce'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),\r
+            'timestamp': ('django.db.models.fields.IntegerField', [], {})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 1, 0, 0, 32, 37000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 2, 0, 0, 32, 86000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0032_auto__del_field_user_hide_ignored_questions__del_field_user_questions_.py b/forum/modules/template_loader.py/forum/migrations/0032_auto__del_field_user_hide_ignored_questions__del_field_user_questions_.py
new file mode 100644 (file)
index 0000000..7a15772
--- /dev/null
@@ -0,0 +1,263 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import SchemaMigration\r
+from django.db import models\r
+\r
+class Migration(SchemaMigration):\r
+    \r
+    def forwards(self, orm):\r
+        \r
+        # Deleting field 'User.hide_ignored_questions'\r
+        db.delete_column('forum_user', 'hide_ignored_questions')\r
+\r
+        # Deleting field 'User.questions_per_page'\r
+        db.delete_column('forum_user', 'questions_per_page')\r
+\r
+        # Deleting field 'User.email_key'\r
+        db.delete_column('forum_user', 'email_key')\r
+\r
+        # Adding field 'Node.in_moderation'\r
+        db.add_column('forum_node', 'in_moderation', self.gf('django.db.models.fields.related.ForeignKey')(related_name='moderated_node', unique=True, null=True, to=orm['forum.Action']), keep_default=False)\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        \r
+        # Adding field 'User.hide_ignored_questions'\r
+        db.add_column('forum_user', 'hide_ignored_questions', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True), keep_default=False)\r
+\r
+        # Adding field 'User.questions_per_page'\r
+        db.add_column('forum_user', 'questions_per_page', self.gf('django.db.models.fields.SmallIntegerField')(default=10), keep_default=False)\r
+\r
+        # Adding field 'User.email_key'\r
+        db.add_column('forum_user', 'email_key', self.gf('django.db.models.fields.CharField')(max_length=32, null=True), keep_default=False)\r
+\r
+        # Deleting field 'Node.in_moderation'\r
+        db.delete_column('forum_node', 'in_moderation_id')\r
+    \r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.action': {\r
+            'Meta': {'object_name': 'Action'},\r
+            'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),\r
+            'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.actionrepute': {\r
+            'Meta': {'object_name': 'ActionRepute'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}),\r
+            'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'deleted': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'deleted_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'extra_action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'extra_node'", 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'in_moderation': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'moderated_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.openidassociation': {\r
+            'Meta': {'object_name': 'OpenIdAssociation'},\r
+            'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}),\r
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'issued': ('django.db.models.fields.IntegerField', [], {}),\r
+            'lifetime': ('django.db.models.fields.IntegerField', [], {}),\r
+            'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}),\r
+            'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'})\r
+        },\r
+        'forum.openidnonce': {\r
+            'Meta': {'object_name': 'OpenIdNonce'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),\r
+            'timestamp': ('django.db.models.fields.IntegerField', [], {})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 2, 4, 54, 13, 72000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 3, 4, 54, 13, 256000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0033_auto__add_flag__add_vote__add_field_badge_cls__del_unique_badge_type_n.py b/forum/modules/template_loader.py/forum/migrations/0033_auto__add_flag__add_vote__add_field_badge_cls__del_unique_badge_type_n.py
new file mode 100644 (file)
index 0000000..f2b38e8
--- /dev/null
@@ -0,0 +1,333 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import SchemaMigration\r
+from django.db import models\r
+\r
+class Migration(SchemaMigration):\r
+    \r
+    def forwards(self, orm):\r
+        db.rename_table('award', 'forum_award')\r
+        db.rename_table('badge', 'forum_badge')\r
+        db.rename_table('tag', 'forum_tag')\r
+        \r
+        # Adding model 'Flag'\r
+        db.create_table('forum_flag', (\r
+            ('node', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.Node'])),\r
+            ('action', self.gf('django.db.models.fields.related.ForeignKey')(related_name='flag', unique=True, to=orm['forum.Action'])),\r
+            ('reason', self.gf('django.db.models.fields.CharField')(max_length=300)),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.User'])),\r
+            ('flagged_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+        ))\r
+        #db.send_create_signal('forum', ['Flag'])\r
+\r
+        # Adding model 'Vote'\r
+        db.create_table('forum_vote', (\r
+            ('node', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.Node'])),\r
+            ('action', self.gf('django.db.models.fields.related.ForeignKey')(related_name='vote', unique=True, to=orm['forum.Action'])),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('value', self.gf('django.db.models.fields.SmallIntegerField')()),\r
+            ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.User'])),\r
+            ('voted_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),\r
+        ))\r
+        #db.send_create_signal('forum', ['Vote'])\r
+\r
+        # Adding field 'Badge.cls'\r
+        db.add_column('forum_badge', 'cls', self.gf('django.db.models.fields.CharField')(max_length=50, null=True), keep_default=False)\r
+\r
+        # Removing unique constraint on 'Badge', fields ['type', 'name']\r
+        db.delete_unique(u'forum_badge', ['type', 'name'])\r
+\r
+        # Deleting field 'Award.notified'\r
+        db.delete_column(u'forum_award', 'notified')\r
+\r
+        # Adding field 'Award.node'\r
+        db.add_column('forum_award', 'node', self.gf('django.db.models.fields.related.ForeignKey')(default=1, to=orm['forum.Node'], null=True), keep_default=False)\r
+\r
+        # Adding field 'Award.trigger'\r
+        db.add_column('forum_award', 'trigger', self.gf('django.db.models.fields.related.ForeignKey')(related_name='awards', null=True, to=orm['forum.Action']), keep_default=False)\r
+\r
+        # Adding field 'Award.action'\r
+        db.add_column('forum_award', 'action', self.gf('django.db.models.fields.related.ForeignKey')(default=1, related_name='award', to=orm['forum.Action']), keep_default=False)\r
+\r
+        # Adding unique constraint on 'Award', fields ['node', 'badge', 'user']\r
+        #db.create_unique('forum_award', ['node_id', 'badge_id', 'user_id'])\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        \r
+        # Deleting model 'Flag'\r
+        db.delete_table('forum_flag')\r
+\r
+        # Deleting model 'Vote'\r
+        db.delete_table('forum_vote')\r
+\r
+        # Deleting field 'Badge.cls'\r
+        db.delete_column('forum_badge', 'cls')\r
+\r
+        # Adding unique constraint on 'Badge', fields ['type', 'name']\r
+        db.create_unique(u'badge', ['type', 'name'])\r
+\r
+        # Adding field 'Award.notified'\r
+        db.add_column(u'award', 'notified', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True), keep_default=False)\r
+\r
+        # Deleting field 'Award.node'\r
+        db.delete_column('forum_award', 'node_id')\r
+\r
+        # Deleting field 'Award.trigger'\r
+        db.delete_column('forum_award', 'trigger_id')\r
+\r
+        # Deleting field 'Award.action'\r
+        db.delete_column('forum_award', 'action_id')\r
+\r
+        # Removing unique constraint on 'Award', fields ['node', 'badge', 'user']\r
+        db.delete_unique('forum_award', ['node_id', 'badge_id', 'user_id'])\r
+    \r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.action': {\r
+            'Meta': {'object_name': 'Action'},\r
+            'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),\r
+            'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.actionrepute': {\r
+            'Meta': {'object_name': 'ActionRepute'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}),\r
+            'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('user', 'badge', 'node'),)", 'object_name': 'Award'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award'", 'to': "orm['forum.Action']"}),\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'trigger': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'object_name': 'Badge'},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'cls': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.flag': {\r
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Flag'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flag'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'deleted': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'deleted_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'extra_action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'extra_node'", 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'in_moderation': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'moderated_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.openidassociation': {\r
+            'Meta': {'object_name': 'OpenIdAssociation'},\r
+            'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}),\r
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'issued': ('django.db.models.fields.IntegerField', [], {}),\r
+            'lifetime': ('django.db.models.fields.IntegerField', [], {}),\r
+            'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}),\r
+            'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'})\r
+        },\r
+        'forum.openidnonce': {\r
+            'Meta': {'object_name': 'OpenIdNonce'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),\r
+            'timestamp': ('django.db.models.fields.IntegerField', [], {})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 3, 11, 41, 55, 831000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag'},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 4, 11, 41, 59, 140000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Vote'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vote'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0034_new_badge_and_award.py b/forum/modules/template_loader.py/forum/migrations/0034_new_badge_and_award.py
new file mode 100644 (file)
index 0000000..89399f9
--- /dev/null
@@ -0,0 +1,344 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import DataMigration\r
+from django.db import models\r
+from forum.migrations import ProgressBar\r
+from forum.models.utils import dbsafe_decode\r
+\r
+class Migration(DataMigration):\r
+\r
+    def forwards(self, orm):\r
+        b_count = orm.Badge.objects.count()\r
+        print "\nConverting %d badges:" % b_count\r
+        progress = ProgressBar(b_count)\r
+\r
+        for b in orm.Badge.objects.all():\r
+            b.cls = "".join([s[0].upper() + s[1:] for s in b.slug.split('-')])\r
+            b.save()\r
+\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+\r
+        ctypes = dict([(ct.name, ct.id) for ct in orm['contenttypes.ContentType'].objects.all()])\r
+\r
+        a_count = orm.Award.objects.count()\r
+        print "\nConverting %d awards:" % a_count\r
+        progress = ProgressBar(a_count)\r
+\r
+        for a in orm.Award.objects.all():\r
+            if a.content_type.id == ctypes['user']:\r
+                a.node = None\r
+            else:\r
+                try:\r
+                    a.node = orm.Node.objects.get(id=a.object_id)\r
+                except:\r
+                    a.delete()\r
+                    continue\r
+\r
+            action = orm.Action(\r
+                user = a.user,\r
+                node = a.node,\r
+                action_type = "award",\r
+                action_date = a.awarded_at,\r
+            )\r
+\r
+            action.save()\r
+\r
+            a.action = action\r
+            a.save()\r
+\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+\r
+\r
+        a_count = orm.Action.objects.filter(action_type__in=("voteup", "votedown", "voteupcomment")).count()\r
+        print "\nConverting %d votes:" % a_count\r
+        progress = ProgressBar(a_count)\r
+\r
+        for a in orm.Action.objects.filter(action_type__in=("voteup", "votedown", "voteupcomment"), canceled=False):\r
+            v = orm.Vote(\r
+                user = a.user,\r
+                node = a.node,\r
+                value = (a.action_type in ("voteup", "voteupcomment")) and 1 or -1,\r
+                action = a,\r
+                voted_at = a.action_date\r
+            )\r
+\r
+            v.save()\r
+\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+\r
+        a_count = orm.Action.objects.filter(action_type__in=("voteup", "votedown", "voteupcomment")).count()\r
+        print "\nConverting %d votes:" % a_count\r
+        progress = ProgressBar(a_count)\r
+\r
+        for a in orm.Action.objects.filter(action_type="flag", canceled=False):\r
+            f = orm.Flag(\r
+                user = a.user,\r
+                node = a.node,\r
+                reason = a.extra,\r
+                action = a,\r
+                flagged_at = a.action_date\r
+            )\r
+\r
+            f.save()\r
+\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        "Write your backwards methods here."\r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.action': {\r
+            'Meta': {'object_name': 'Action'},\r
+            'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),\r
+            'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.actionrepute': {\r
+            'Meta': {'object_name': 'ActionRepute'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}),\r
+            'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('user', 'badge', 'node'),)", 'object_name': 'Award'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award'", 'to': "orm['forum.Action']"}),\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'trigger': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'object_name': 'Badge'},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'cls': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.flag': {\r
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Flag'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flag'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'deleted': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'deleted_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'extra_action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'extra_node'", 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'in_moderation': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'moderated_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.openidassociation': {\r
+            'Meta': {'object_name': 'OpenIdAssociation'},\r
+            'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}),\r
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'issued': ('django.db.models.fields.IntegerField', [], {}),\r
+            'lifetime': ('django.db.models.fields.IntegerField', [], {}),\r
+            'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}),\r
+            'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'})\r
+        },\r
+        'forum.openidnonce': {\r
+            'Meta': {'object_name': 'OpenIdNonce'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),\r
+            'timestamp': ('django.db.models.fields.IntegerField', [], {})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 3, 11, 43, 54, 540000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag'},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 4, 11, 43, 54, 592000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Vote'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vote'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0035_auto__del_field_award_object_id__del_field_award_content_type__add_uni.py b/forum/modules/template_loader.py/forum/migrations/0035_auto__del_field_award_object_id__del_field_award_content_type__add_uni.py
new file mode 100644 (file)
index 0000000..b566ef0
--- /dev/null
@@ -0,0 +1,296 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import SchemaMigration\r
+from django.db import models\r
+\r
+class Migration(SchemaMigration):\r
+    \r
+    def forwards(self, orm):\r
+        \r
+        # Deleting field 'Award.object_id'\r
+        db.delete_column('forum_award', 'object_id')\r
+\r
+        # Deleting field 'Award.content_type'\r
+        db.delete_column('forum_award', 'content_type_id')\r
+\r
+        # Adding unique constraint on 'Award', fields ['action']\r
+        db.create_unique('forum_award', ['action_id'])\r
+\r
+        # Deleting field 'Badge.multiple'\r
+        db.delete_column('forum_badge', 'multiple')\r
+\r
+        # Deleting field 'Badge.name'\r
+        db.delete_column('forum_badge', 'name')\r
+\r
+        # Deleting field 'Badge.slug'\r
+        db.delete_column('forum_badge', 'slug')\r
+\r
+        # Deleting field 'Badge.description'\r
+        db.delete_column('forum_badge', 'description')\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        \r
+        # Adding field 'Award.object_id'\r
+        db.add_column('forum_award', 'object_id', self.gf('django.db.models.fields.PositiveIntegerField')(default=1), keep_default=False)\r
+\r
+        # Adding field 'Award.content_type'\r
+        db.add_column('forum_award', 'content_type', self.gf('django.db.models.fields.related.ForeignKey')(default=1, to=orm['contenttypes.ContentType']), keep_default=False)\r
+\r
+        # Removing unique constraint on 'Award', fields ['action']\r
+        db.delete_unique('forum_award', ['action_id'])\r
+\r
+        # Adding field 'Badge.multiple'\r
+        db.add_column('forum_badge', 'multiple', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True), keep_default=False)\r
+\r
+        # Adding field 'Badge.name'\r
+        db.add_column('forum_badge', 'name', self.gf('django.db.models.fields.CharField')(default=1, max_length=50), keep_default=False)\r
+\r
+        # Adding field 'Badge.slug'\r
+        db.add_column('forum_badge', 'slug', self.gf('django.db.models.fields.SlugField')(blank=True, default=1, max_length=50, db_index=True), keep_default=False)\r
+\r
+        # Adding field 'Badge.description'\r
+        db.add_column('forum_badge', 'description', self.gf('django.db.models.fields.CharField')(default=1, max_length=300), keep_default=False)\r
+    \r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.action': {\r
+            'Meta': {'object_name': 'Action'},\r
+            'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),\r
+            'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.actionrepute': {\r
+            'Meta': {'object_name': 'ActionRepute'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}),\r
+            'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('user', 'badge', 'node'),)", 'object_name': 'Award'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Badge']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'trigger': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'object_name': 'Badge'},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'cls': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.flag': {\r
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Flag'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flag'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'deleted': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'deleted_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'extra_action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'extra_node'", 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'in_moderation': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'moderated_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.openidassociation': {\r
+            'Meta': {'object_name': 'OpenIdAssociation'},\r
+            'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}),\r
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'issued': ('django.db.models.fields.IntegerField', [], {}),\r
+            'lifetime': ('django.db.models.fields.IntegerField', [], {}),\r
+            'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}),\r
+            'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'})\r
+        },\r
+        'forum.openidnonce': {\r
+            'Meta': {'object_name': 'OpenIdNonce'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),\r
+            'timestamp': ('django.db.models.fields.IntegerField', [], {})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 3, 11, 46, 22, 80000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag'},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 4, 11, 46, 28, 428000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Vote'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vote'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0036_auto__add_nodestate__chg_field_award_action__add_field_node_state_stri.py b/forum/modules/template_loader.py/forum/migrations/0036_auto__add_nodestate__chg_field_award_action__add_field_node_state_stri.py
new file mode 100644 (file)
index 0000000..ac16256
--- /dev/null
@@ -0,0 +1,298 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import SchemaMigration\r
+from django.db import models\r
+\r
+class Migration(SchemaMigration):\r
+    \r
+    def forwards(self, orm):\r
+        \r
+        # Adding model 'NodeState'\r
+        db.create_table('forum_nodestate', (\r
+            ('node', self.gf('django.db.models.fields.related.ForeignKey')(related_name='state', to=orm['forum.Node'])),\r
+            ('state_type', self.gf('django.db.models.fields.CharField')(max_length=16)),\r
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),\r
+            ('action', self.gf('django.db.models.fields.related.ForeignKey')(related_name='node_state', unique=True, to=orm['forum.Action'])),\r
+        ))\r
+        db.send_create_signal('forum', ['NodeState'])\r
+\r
+        # Changing field 'Award.action'\r
+        db.alter_column('forum_award', 'action_id', self.gf('django.db.models.fields.related.OneToOneField')(unique=True, to=orm['forum.Action']))\r
+\r
+        # Adding field 'Node.state_string'\r
+        db.add_column('forum_node', 'state_string', self.gf('django.db.models.fields.TextField')(default=''), keep_default=False)\r
+\r
+        # Changing field 'Flag.action'\r
+        db.alter_column('forum_flag', 'action_id', self.gf('django.db.models.fields.related.OneToOneField')(unique=True, to=orm['forum.Action']))\r
+\r
+        # Changing field 'Vote.action'\r
+        db.alter_column('forum_vote', 'action_id', self.gf('django.db.models.fields.related.OneToOneField')(unique=True, to=orm['forum.Action']))\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        \r
+        # Deleting model 'NodeState'\r
+        db.delete_table('forum_nodestate')\r
+\r
+        # Changing field 'Award.action'\r
+        db.alter_column('forum_award', 'action_id', self.gf('django.db.models.fields.related.ForeignKey')(unique=True, to=orm['forum.Action']))\r
+\r
+        # Deleting field 'Node.state_string'\r
+        db.delete_column('forum_node', 'state_string')\r
+\r
+        # Changing field 'Flag.action'\r
+        db.alter_column('forum_flag', 'action_id', self.gf('django.db.models.fields.related.ForeignKey')(unique=True, to=orm['forum.Action']))\r
+\r
+        # Changing field 'Vote.action'\r
+        db.alter_column('forum_vote', 'action_id', self.gf('django.db.models.fields.related.ForeignKey')(unique=True, to=orm['forum.Action']))\r
+    \r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.action': {\r
+            'Meta': {'object_name': 'Action'},\r
+            'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),\r
+            'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.actionrepute': {\r
+            'Meta': {'object_name': 'ActionRepute'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}),\r
+            'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('user', 'badge', 'node'),)", 'object_name': 'Award'},\r
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'award'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.Badge']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'trigger': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'object_name': 'Badge'},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'symmetrical': 'False', 'through': "orm['forum.Award']", 'to': "orm['forum.User']"}),\r
+            'cls': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.flag': {\r
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Flag'},\r
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'flag'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flags'", 'to': "orm['forum.Node']"}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flags'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'deleted': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'deleted_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'extra_action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'extra_node'", 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'in_moderation': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'moderated_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'state_string': ('django.db.models.fields.TextField', [], {'default': "''"}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'symmetrical': 'False', 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.nodestate': {\r
+            'Meta': {'unique_together': "(('node', 'state_type'),)", 'object_name': 'NodeState'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'node_state'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'state'", 'to': "orm['forum.Node']"}),\r
+            'state_type': ('django.db.models.fields.CharField', [], {'max_length': '16'})\r
+        },\r
+        'forum.openidassociation': {\r
+            'Meta': {'object_name': 'OpenIdAssociation'},\r
+            'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}),\r
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'issued': ('django.db.models.fields.IntegerField', [], {}),\r
+            'lifetime': ('django.db.models.fields.IntegerField', [], {}),\r
+            'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}),\r
+            'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'})\r
+        },\r
+        'forum.openidnonce': {\r
+            'Meta': {'object_name': 'OpenIdNonce'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),\r
+            'timestamp': ('django.db.models.fields.IntegerField', [], {})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 24, 12, 24, 54, 587000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag'},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'symmetrical': 'False', 'through': "orm['forum.MarkedTag']", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'symmetrical': 'False', 'through': "orm['forum.QuestionSubscription']", 'to': "orm['forum.Node']"}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 25, 12, 24, 54, 760000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Vote'},\r
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'vote'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0037_fill_node_state.py b/forum/modules/template_loader.py/forum/migrations/0037_fill_node_state.py
new file mode 100644 (file)
index 0000000..79ed9c9
--- /dev/null
@@ -0,0 +1,317 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import DataMigration\r
+from django.db import models\r
+from forum.migrations import ProgressBar\r
+\r
+class Migration(DataMigration):\r
+    \r
+    def forwards(self, orm):\r
+        n_count = orm.Node.objects.count()\r
+        print "\nConverting %s node states:" % n_count\r
+        progress = ProgressBar(n_count)\r
+\r
+        for n in orm.Node.objects.all():\r
+            ss = ""\r
+\r
+            if n.deleted:\r
+                s = orm.NodeState(\r
+                    node = n,\r
+                    action = n.deleted,\r
+                    state_type = "deleted"\r
+                )\r
+                s.save()\r
+                ss += "(deleted)"\r
+\r
+            if n.wiki:\r
+                try:\r
+                    action = orm.Action.objects.get(node=n, action_type="wikify")\r
+                    s = orm.NodeState(\r
+                        node = n,\r
+                        action = action,\r
+                        state_type = "wiki"\r
+                    )\r
+                    s.save()\r
+                    ss += "(wiki)"\r
+                except:\r
+                    pass\r
+\r
+            if n.node_type == "question" and n.extra_action:\r
+                s = orm.NodeState(\r
+                    node = n,\r
+                    action = n.extra_action,\r
+                    state_type = "closed"\r
+                )\r
+                s.save()\r
+                ss += "(closed)"\r
+\r
+            if n.node_type == "answer" and n.extra_action:\r
+                s = orm.NodeState(\r
+                    node = n,\r
+                    action = n.extra_action,\r
+                    state_type = "accepted"\r
+                )\r
+                s.save()\r
+                ss += "(accepted)"\r
+\r
+            if ss:\r
+                n.state_string = ss\r
+                n.save()\r
+\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        "Write your backwards methods here."\r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.action': {\r
+            'Meta': {'object_name': 'Action'},\r
+            'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),\r
+            'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.actionrepute': {\r
+            'Meta': {'object_name': 'ActionRepute'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}),\r
+            'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('user', 'badge', 'node'),)", 'object_name': 'Award'},\r
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'award'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.Badge']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'trigger': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'object_name': 'Badge'},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'symmetrical': 'False', 'through': "orm['forum.Award']", 'to': "orm['forum.User']"}),\r
+            'cls': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.flag': {\r
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Flag'},\r
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'flag'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flags'", 'to': "orm['forum.Node']"}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flags'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'deleted': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'deleted_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'extra_action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'extra_node'", 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'in_moderation': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'moderated_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'state_string': ('django.db.models.fields.TextField', [], {'default': "''"}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'symmetrical': 'False', 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.nodestate': {\r
+            'Meta': {'unique_together': "(('node', 'state_type'),)", 'object_name': 'NodeState'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'node_state'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'state'", 'to': "orm['forum.Node']"}),\r
+            'state_type': ('django.db.models.fields.CharField', [], {'max_length': '16'})\r
+        },\r
+        'forum.openidassociation': {\r
+            'Meta': {'object_name': 'OpenIdAssociation'},\r
+            'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}),\r
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'issued': ('django.db.models.fields.IntegerField', [], {}),\r
+            'lifetime': ('django.db.models.fields.IntegerField', [], {}),\r
+            'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}),\r
+            'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'})\r
+        },\r
+        'forum.openidnonce': {\r
+            'Meta': {'object_name': 'OpenIdNonce'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),\r
+            'timestamp': ('django.db.models.fields.IntegerField', [], {})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 24, 12, 26, 33, 742000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag'},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'symmetrical': 'False', 'through': "orm['forum.MarkedTag']", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'symmetrical': 'False', 'through': "orm['forum.QuestionSubscription']", 'to': "orm['forum.Node']"}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 25, 12, 26, 33, 797000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Vote'},\r
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'vote'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0038_auto__del_field_node_wiki__del_field_node_deleted__del_field_node_extr.py b/forum/modules/template_loader.py/forum/migrations/0038_auto__del_field_node_wiki__del_field_node_deleted__del_field_node_extr.py
new file mode 100644 (file)
index 0000000..c38e21f
--- /dev/null
@@ -0,0 +1,282 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import SchemaMigration\r
+from django.db import models\r
+\r
+class Migration(SchemaMigration):\r
+    \r
+    def forwards(self, orm):\r
+        \r
+        # Deleting field 'Node.wiki'\r
+        db.delete_column('forum_node', 'wiki')\r
+\r
+        # Deleting field 'Node.deleted'\r
+        db.delete_column('forum_node', 'deleted_id')\r
+\r
+        # Deleting field 'Node.extra_action'\r
+        db.delete_column('forum_node', 'extra_action_id')\r
+\r
+        # Deleting field 'Node.in_moderation'\r
+        db.delete_column('forum_node', 'in_moderation_id')\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        \r
+        # Adding field 'Node.wiki'\r
+        db.add_column('forum_node', 'wiki', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True), keep_default=False)\r
+\r
+        # Adding field 'Node.deleted'\r
+        db.add_column('forum_node', 'deleted', self.gf('django.db.models.fields.related.ForeignKey')(related_name='deleted_node', unique=True, null=True, to=orm['forum.Action']), keep_default=False)\r
+\r
+        # Adding field 'Node.extra_action'\r
+        db.add_column('forum_node', 'extra_action', self.gf('django.db.models.fields.related.ForeignKey')(related_name='extra_node', null=True, to=orm['forum.Action']), keep_default=False)\r
+\r
+        # Adding field 'Node.in_moderation'\r
+        db.add_column('forum_node', 'in_moderation', self.gf('django.db.models.fields.related.ForeignKey')(related_name='moderated_node', unique=True, null=True, to=orm['forum.Action']), keep_default=False)\r
+    \r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.action': {\r
+            'Meta': {'object_name': 'Action'},\r
+            'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),\r
+            'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.actionrepute': {\r
+            'Meta': {'object_name': 'ActionRepute'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}),\r
+            'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('user', 'badge', 'node'),)", 'object_name': 'Award'},\r
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'award'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.Badge']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'trigger': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'object_name': 'Badge'},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'symmetrical': 'False', 'through': "orm['forum.Award']", 'to': "orm['forum.User']"}),\r
+            'cls': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.flag': {\r
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Flag'},\r
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'flag'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flags'", 'to': "orm['forum.Node']"}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flags'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'state_string': ('django.db.models.fields.TextField', [], {'default': "''"}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'symmetrical': 'False', 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.nodestate': {\r
+            'Meta': {'unique_together': "(('node', 'state_type'),)", 'object_name': 'NodeState'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'node_state'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'states'", 'to': "orm['forum.Node']"}),\r
+            'state_type': ('django.db.models.fields.CharField', [], {'max_length': '16'})\r
+        },\r
+        'forum.openidassociation': {\r
+            'Meta': {'object_name': 'OpenIdAssociation'},\r
+            'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}),\r
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'issued': ('django.db.models.fields.IntegerField', [], {}),\r
+            'lifetime': ('django.db.models.fields.IntegerField', [], {}),\r
+            'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}),\r
+            'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'})\r
+        },\r
+        'forum.openidnonce': {\r
+            'Meta': {'object_name': 'OpenIdNonce'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),\r
+            'timestamp': ('django.db.models.fields.IntegerField', [], {})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 24, 19, 29, 24, 232000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag'},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'symmetrical': 'False', 'through': "orm['forum.MarkedTag']", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'symmetrical': 'False', 'through': "orm['forum.QuestionSubscription']", 'to': "orm['forum.Node']"}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 25, 19, 29, 24, 443000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Vote'},\r
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'vote'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0039_auto__del_field_tag_deleted__del_field_tag_deleted_by__del_field_tag_d.py b/forum/modules/template_loader.py/forum/migrations/0039_auto__del_field_tag_deleted__del_field_tag_deleted_by__del_field_tag_d.py
new file mode 100644 (file)
index 0000000..4a91aa7
--- /dev/null
@@ -0,0 +1,273 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import SchemaMigration\r
+from django.db import models\r
+\r
+class Migration(SchemaMigration):\r
+    \r
+    def forwards(self, orm):\r
+        \r
+        # Deleting field 'Tag.deleted'\r
+        db.delete_column('forum_tag', 'deleted')\r
+\r
+        # Deleting field 'Tag.deleted_by'\r
+        db.delete_column('forum_tag', 'deleted_by_id')\r
+\r
+        # Deleting field 'Tag.deleted_at'\r
+        db.delete_column('forum_tag', 'deleted_at')\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        \r
+        # Adding field 'Tag.deleted'\r
+        db.add_column('forum_tag', 'deleted', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True), keep_default=False)\r
+\r
+        # Adding field 'Tag.deleted_by'\r
+        db.add_column('forum_tag', 'deleted_by', self.gf('django.db.models.fields.related.ForeignKey')(related_name='deleted_tags', null=True, to=orm['forum.User'], blank=True), keep_default=False)\r
+\r
+        # Adding field 'Tag.deleted_at'\r
+        db.add_column('forum_tag', 'deleted_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True), keep_default=False)\r
+    \r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.action': {\r
+            'Meta': {'object_name': 'Action'},\r
+            'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),\r
+            'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.actionrepute': {\r
+            'Meta': {'object_name': 'ActionRepute'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}),\r
+            'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('user', 'badge', 'node'),)", 'object_name': 'Award'},\r
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'award'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.Badge']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'trigger': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'object_name': 'Badge'},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'symmetrical': 'False', 'through': "orm['forum.Award']", 'to': "orm['forum.User']"}),\r
+            'cls': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.flag': {\r
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Flag'},\r
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'flag'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flags'", 'to': "orm['forum.Node']"}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flags'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'state_string': ('django.db.models.fields.TextField', [], {'default': "''"}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'symmetrical': 'False', 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.nodestate': {\r
+            'Meta': {'unique_together': "(('node', 'state_type'),)", 'object_name': 'NodeState'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'node_state'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'states'", 'to': "orm['forum.Node']"}),\r
+            'state_type': ('django.db.models.fields.CharField', [], {'max_length': '16'})\r
+        },\r
+        'forum.openidassociation': {\r
+            'Meta': {'object_name': 'OpenIdAssociation'},\r
+            'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}),\r
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'issued': ('django.db.models.fields.IntegerField', [], {}),\r
+            'lifetime': ('django.db.models.fields.IntegerField', [], {}),\r
+            'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}),\r
+            'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'})\r
+        },\r
+        'forum.openidnonce': {\r
+            'Meta': {'object_name': 'OpenIdNonce'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),\r
+            'timestamp': ('django.db.models.fields.IntegerField', [], {})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 25, 0, 18, 31, 631000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag'},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'symmetrical': 'False', 'through': "orm['forum.MarkedTag']", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'symmetrical': 'False', 'through': "orm['forum.QuestionSubscription']", 'to': "orm['forum.Node']"}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 26, 0, 18, 31, 914000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Vote'},\r
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'vote'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/modules/template_loader.py/forum/migrations/0040_auto__chg_field_nodestate_action__add_field_node_extra.py b/forum/modules/template_loader.py/forum/migrations/0040_auto__chg_field_nodestate_action__add_field_node_extra.py
new file mode 100644 (file)
index 0000000..0b28278
--- /dev/null
@@ -0,0 +1,260 @@
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding field 'Node.extra'
+        db.add_column('forum_node', 'extra', self.gf('forum.models.utils.PickledObjectField')(null=True), keep_default=False)
+
+
+    def backwards(self, orm):
+        # Deleting field 'Node.extra'
+        db.delete_column('forum_node', 'extra')
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'forum.action': {
+            'Meta': {'object_name': 'Action'},
+            'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
+            'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}),
+            'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+            'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"})
+        },
+        'forum.actionrepute': {
+            'Meta': {'object_name': 'ActionRepute'},
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}),
+            'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),
+            'value': ('django.db.models.fields.IntegerField', [], {'default': '0'})
+        },
+        'forum.authkeyuserassociation': {
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})
+        },
+        'forum.award': {
+            'Meta': {'unique_together': "(('user', 'badge', 'node'),)", 'object_name': 'Award'},
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'award'", 'unique': 'True', 'to': "orm['forum.Action']"}),
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.Badge']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),
+            'trigger': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'null': 'True', 'to': "orm['forum.Action']"}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})
+        },
+        'forum.badge': {
+            'Meta': {'object_name': 'Badge'},
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'symmetrical': 'False', 'through': "orm['forum.Award']", 'to': "orm['forum.User']"}),
+            'cls': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})
+        },
+        'forum.flag': {
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Flag'},
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'flag'", 'unique': 'True', 'to': "orm['forum.Action']"}),
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flags'", 'to': "orm['forum.Node']"}),
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flags'", 'to': "orm['forum.User']"})
+        },
+        'forum.keyvalue': {
+            'Meta': {'object_name': 'KeyValue'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+            'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'})
+        },
+        'forum.markedtag': {
+            'Meta': {'object_name': 'MarkedTag'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})
+        },
+        'forum.node': {
+            'Meta': {'object_name': 'Node'},
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),
+            'body': ('django.db.models.fields.TextField', [], {}),
+            'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}),
+            'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),
+            'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),
+            'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            'state_string': ('django.db.models.fields.TextField', [], {'default': "''"}),
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'symmetrical': 'False', 'to': "orm['forum.Tag']"}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})
+        },
+        'forum.noderevision': {
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),
+            'body': ('django.db.models.fields.TextField', [], {}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})
+        },
+        'forum.nodestate': {
+            'Meta': {'unique_together': "(('node', 'state_type'),)", 'object_name': 'NodeState'},
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'node_state'", 'unique': 'True', 'to': "orm['forum.Action']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'states'", 'to': "orm['forum.Node']"}),
+            'state_type': ('django.db.models.fields.CharField', [], {'max_length': '16'})
+        },
+        'forum.openidassociation': {
+            'Meta': {'object_name': 'OpenIdAssociation'},
+            'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}),
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'issued': ('django.db.models.fields.IntegerField', [], {}),
+            'lifetime': ('django.db.models.fields.IntegerField', [], {}),
+            'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}),
+            'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'})
+        },
+        'forum.openidnonce': {
+            'Meta': {'object_name': 'OpenIdNonce'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+            'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
+            'timestamp': ('django.db.models.fields.IntegerField', [], {})
+        },
+        'forum.questionsubscription': {
+            'Meta': {'object_name': 'QuestionSubscription'},
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 6, 4, 12, 12, 32, 595305)'}),
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})
+        },
+        'forum.subscriptionsettings': {
+            'Meta': {'object_name': 'SubscriptionSettings'},
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})
+        },
+        'forum.tag': {
+            'Meta': {'object_name': 'Tag'},
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'symmetrical': 'False', 'through': "orm['forum.MarkedTag']", 'to': "orm['forum.User']"}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
+        },
+        'forum.user': {
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'symmetrical': 'False', 'through': "orm['forum.QuestionSubscription']", 'to': "orm['forum.Node']"}),
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})
+        },
+        'forum.validationhash': {
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 6, 5, 12, 12, 32, 734979)'}),
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})
+        },
+        'forum.vote': {
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Vote'},
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'vote'", 'unique': 'True', 'to': "orm['forum.Action']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.Node']"}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),
+            'value': ('django.db.models.fields.SmallIntegerField', [], {}),
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})
+        }
+    }
+
+    complete_apps = ['forum']
diff --git a/forum/modules/template_loader.py/forum/migrations/0041_action_ip_fixes.py b/forum/modules/template_loader.py/forum/migrations/0041_action_ip_fixes.py
new file mode 100644 (file)
index 0000000..9c8a24f
--- /dev/null
@@ -0,0 +1,300 @@
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import DataMigration
+from django.db import models
+from forum.migrations import ProgressBar
+
+class Migration(DataMigration):
+
+    def forwards(self, orm):
+        a_count = orm.Action.objects.filter(action_type="bonusrep").count()
+        print "\nConverting %s bonus actions:" % a_count
+        progress = ProgressBar(a_count)
+
+        for a in orm.Action.objects.filter(action_type="bonusrep"):
+            a.user = orm.User.objects.get(id=a.extra['awarding_user'])
+            a.save()
+
+            progress.update()
+
+        print "\n...done\n"
+
+
+        s_count = orm.Action.objects.filter(action_type="suspend").count()
+        print "\nConverting %s suspend actions:" % a_count
+        progress = ProgressBar(s_count)
+
+        for a in orm.Action.objects.filter(action_type="suspend"):
+            suspended = a.user
+
+            a.user = orm.User.objects.get(id=a.extra['suspender'])
+            a.save()
+
+            rep = orm.ActionRepute(user=suspended, action=a, value=0, date=a.action_date)
+            rep.save()
+
+            progress.update()
+
+        print "\n...done\n"
+
+        a_count = orm.Action.objects.filter(action_type="award").count()
+        print "\nConverting %s award actions:" % a_count
+        progress = ProgressBar(a_count)
+
+        for a in orm.Action.objects.filter(action_type="award"):
+            a.ip = ''
+            a.save()
+
+            progress.update()
+
+        print "\n...done\n"
+
+
+
+    def backwards(self, orm):
+        "Write your backwards methods here."
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'forum.action': {
+            'Meta': {'object_name': 'Action'},
+            'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
+            'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}),
+            'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+            'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"})
+        },
+        'forum.actionrepute': {
+            'Meta': {'object_name': 'ActionRepute'},
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}),
+            'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),
+            'value': ('django.db.models.fields.IntegerField', [], {'default': '0'})
+        },
+        'forum.authkeyuserassociation': {
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})
+        },
+        'forum.award': {
+            'Meta': {'unique_together': "(('user', 'badge', 'node'),)", 'object_name': 'Award'},
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'award'", 'unique': 'True', 'to': "orm['forum.Action']"}),
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.Badge']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),
+            'trigger': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'null': 'True', 'to': "orm['forum.Action']"}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})
+        },
+        'forum.badge': {
+            'Meta': {'object_name': 'Badge'},
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'symmetrical': 'False', 'through': "orm['forum.Award']", 'to': "orm['forum.User']"}),
+            'cls': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})
+        },
+        'forum.flag': {
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Flag'},
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'flag'", 'unique': 'True', 'to': "orm['forum.Action']"}),
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flags'", 'to': "orm['forum.Node']"}),
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flags'", 'to': "orm['forum.User']"})
+        },
+        'forum.keyvalue': {
+            'Meta': {'object_name': 'KeyValue'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+            'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'})
+        },
+        'forum.markedtag': {
+            'Meta': {'object_name': 'MarkedTag'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})
+        },
+        'forum.node': {
+            'Meta': {'object_name': 'Node'},
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),
+            'body': ('django.db.models.fields.TextField', [], {}),
+            'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}),
+            'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),
+            'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),
+            'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            'state_string': ('django.db.models.fields.TextField', [], {'default': "''"}),
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'symmetrical': 'False', 'to': "orm['forum.Tag']"}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})
+        },
+        'forum.noderevision': {
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),
+            'body': ('django.db.models.fields.TextField', [], {}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})
+        },
+        'forum.nodestate': {
+            'Meta': {'unique_together': "(('node', 'state_type'),)", 'object_name': 'NodeState'},
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'node_state'", 'unique': 'True', 'to': "orm['forum.Action']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'states'", 'to': "orm['forum.Node']"}),
+            'state_type': ('django.db.models.fields.CharField', [], {'max_length': '16'})
+        },
+        'forum.openidassociation': {
+            'Meta': {'object_name': 'OpenIdAssociation'},
+            'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}),
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'issued': ('django.db.models.fields.IntegerField', [], {}),
+            'lifetime': ('django.db.models.fields.IntegerField', [], {}),
+            'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}),
+            'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'})
+        },
+        'forum.openidnonce': {
+            'Meta': {'object_name': 'OpenIdNonce'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+            'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
+            'timestamp': ('django.db.models.fields.IntegerField', [], {})
+        },
+        'forum.questionsubscription': {
+            'Meta': {'object_name': 'QuestionSubscription'},
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 6, 13, 16, 42, 20, 908594)'}),
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})
+        },
+        'forum.subscriptionsettings': {
+            'Meta': {'object_name': 'SubscriptionSettings'},
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})
+        },
+        'forum.tag': {
+            'Meta': {'object_name': 'Tag'},
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'symmetrical': 'False', 'through': "orm['forum.MarkedTag']", 'to': "orm['forum.User']"}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
+        },
+        'forum.user': {
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'symmetrical': 'False', 'through': "orm['forum.QuestionSubscription']", 'to': "orm['forum.Node']"}),
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})
+        },
+        'forum.validationhash': {
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 6, 14, 16, 42, 20, 944052)'}),
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})
+        },
+        'forum.vote': {
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Vote'},
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'vote'", 'unique': 'True', 'to': "orm['forum.Action']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.Node']"}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),
+            'value': ('django.db.models.fields.SmallIntegerField', [], {}),
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})
+        }
+    }
+
+    complete_apps = ['forum']
diff --git a/forum/modules/template_loader.py/forum/migrations/0042_auto__add_userproperty.py b/forum/modules/template_loader.py/forum/migrations/0042_auto__add_userproperty.py
new file mode 100644 (file)
index 0000000..ecbd7c9
--- /dev/null
@@ -0,0 +1,275 @@
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        
+        # Adding model 'UserProperty'
+        db.create_table('forum_userproperty', (
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='properties', to=orm['forum.User'])),
+            ('key', self.gf('django.db.models.fields.CharField')(max_length=16)),
+            ('value', self.gf('forum.models.utils.PickledObjectField')(null=True)),
+        ))
+        db.send_create_signal('forum', ['UserProperty'])
+
+
+    def backwards(self, orm):
+        
+        # Deleting model 'UserProperty'
+        db.delete_table('forum_userproperty')
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'forum.action': {
+            'Meta': {'object_name': 'Action'},
+            'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
+            'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}),
+            'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+            'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"})
+        },
+        'forum.actionrepute': {
+            'Meta': {'object_name': 'ActionRepute'},
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}),
+            'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),
+            'value': ('django.db.models.fields.IntegerField', [], {'default': '0'})
+        },
+        'forum.authkeyuserassociation': {
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})
+        },
+        'forum.award': {
+            'Meta': {'unique_together': "(('user', 'badge', 'node'),)", 'object_name': 'Award'},
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'award'", 'unique': 'True', 'to': "orm['forum.Action']"}),
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.Badge']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),
+            'trigger': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'null': 'True', 'to': "orm['forum.Action']"}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})
+        },
+        'forum.badge': {
+            'Meta': {'object_name': 'Badge'},
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'symmetrical': 'False', 'through': "orm['forum.Award']", 'to': "orm['forum.User']"}),
+            'cls': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})
+        },
+        'forum.flag': {
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Flag'},
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'flag'", 'unique': 'True', 'to': "orm['forum.Action']"}),
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flags'", 'to': "orm['forum.Node']"}),
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flags'", 'to': "orm['forum.User']"})
+        },
+        'forum.keyvalue': {
+            'Meta': {'object_name': 'KeyValue'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+            'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'})
+        },
+        'forum.markedtag': {
+            'Meta': {'object_name': 'MarkedTag'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})
+        },
+        'forum.node': {
+            'Meta': {'object_name': 'Node'},
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),
+            'body': ('django.db.models.fields.TextField', [], {}),
+            'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}),
+            'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),
+            'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),
+            'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            'state_string': ('django.db.models.fields.TextField', [], {'default': "''"}),
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'symmetrical': 'False', 'to': "orm['forum.Tag']"}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})
+        },
+        'forum.noderevision': {
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),
+            'body': ('django.db.models.fields.TextField', [], {}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})
+        },
+        'forum.nodestate': {
+            'Meta': {'unique_together': "(('node', 'state_type'),)", 'object_name': 'NodeState'},
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'node_state'", 'unique': 'True', 'to': "orm['forum.Action']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'states'", 'to': "orm['forum.Node']"}),
+            'state_type': ('django.db.models.fields.CharField', [], {'max_length': '16'})
+        },
+        'forum.openidassociation': {
+            'Meta': {'object_name': 'OpenIdAssociation'},
+            'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}),
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'issued': ('django.db.models.fields.IntegerField', [], {}),
+            'lifetime': ('django.db.models.fields.IntegerField', [], {}),
+            'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}),
+            'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'})
+        },
+        'forum.openidnonce': {
+            'Meta': {'object_name': 'OpenIdNonce'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+            'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
+            'timestamp': ('django.db.models.fields.IntegerField', [], {})
+        },
+        'forum.questionsubscription': {
+            'Meta': {'object_name': 'QuestionSubscription'},
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 6, 30, 19, 11, 19, 580720)'}),
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})
+        },
+        'forum.subscriptionsettings': {
+            'Meta': {'object_name': 'SubscriptionSettings'},
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})
+        },
+        'forum.tag': {
+            'Meta': {'object_name': 'Tag'},
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'symmetrical': 'False', 'through': "orm['forum.MarkedTag']", 'to': "orm['forum.User']"}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
+        },
+        'forum.user': {
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'symmetrical': 'False', 'through': "orm['forum.QuestionSubscription']", 'to': "orm['forum.Node']"}),
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})
+        },
+        'forum.userproperty': {
+            'Meta': {'unique_together': "(('user', 'key'),)", 'object_name': 'UserProperty'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'properties'", 'to': "orm['forum.User']"}),
+            'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'})
+        },
+        'forum.validationhash': {
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 7, 1, 19, 11, 19, 671272)'}),
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})
+        },
+        'forum.vote': {
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Vote'},
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'vote'", 'unique': 'True', 'to': "orm['forum.Action']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.Node']"}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),
+            'value': ('django.db.models.fields.SmallIntegerField', [], {}),
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})
+        }
+    }
+
+    complete_apps = ['forum']
diff --git a/forum/modules/template_loader.py/forum/migrations/0043_auto__add_field_subscriptionsettings_send_digest__add_field_action_rea.py b/forum/modules/template_loader.py/forum/migrations/0043_auto__add_field_subscriptionsettings_send_digest__add_field_action_rea.py
new file mode 100644 (file)
index 0000000..dc25ef0
--- /dev/null
@@ -0,0 +1,277 @@
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        
+        # Adding field 'SubscriptionSettings.send_digest'
+        db.add_column('forum_subscriptionsettings', 'send_digest', self.gf('django.db.models.fields.BooleanField')(default=True, blank=True), keep_default=False)
+
+        # Adding field 'Action.real_user'
+        db.add_column('forum_action', 'real_user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='proxied_actions', null=True, to=orm['forum.User']), keep_default=False)
+
+
+    def backwards(self, orm):
+        
+        # Deleting field 'SubscriptionSettings.send_digest'
+        db.delete_column('forum_subscriptionsettings', 'send_digest')
+
+        # Deleting field 'Action.real_user'
+        db.delete_column('forum_action', 'real_user_id')
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'forum.action': {
+            'Meta': {'object_name': 'Action'},
+            'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
+            'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}),
+            'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+            'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}),
+            'real_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'proxied_actions'", 'null': 'True', 'to': "orm['forum.User']"}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"})
+        },
+        'forum.actionrepute': {
+            'Meta': {'object_name': 'ActionRepute'},
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}),
+            'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),
+            'value': ('django.db.models.fields.IntegerField', [], {'default': '0'})
+        },
+        'forum.authkeyuserassociation': {
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})
+        },
+        'forum.award': {
+            'Meta': {'unique_together': "(('user', 'badge', 'node'),)", 'object_name': 'Award'},
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'award'", 'unique': 'True', 'to': "orm['forum.Action']"}),
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.Badge']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),
+            'trigger': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'null': 'True', 'to': "orm['forum.Action']"}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})
+        },
+        'forum.badge': {
+            'Meta': {'object_name': 'Badge'},
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'symmetrical': 'False', 'through': "orm['forum.Award']", 'to': "orm['forum.User']"}),
+            'cls': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})
+        },
+        'forum.flag': {
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Flag'},
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'flag'", 'unique': 'True', 'to': "orm['forum.Action']"}),
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flags'", 'to': "orm['forum.Node']"}),
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flags'", 'to': "orm['forum.User']"})
+        },
+        'forum.keyvalue': {
+            'Meta': {'object_name': 'KeyValue'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+            'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'})
+        },
+        'forum.markedtag': {
+            'Meta': {'object_name': 'MarkedTag'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})
+        },
+        'forum.node': {
+            'Meta': {'object_name': 'Node'},
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),
+            'body': ('django.db.models.fields.TextField', [], {}),
+            'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}),
+            'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),
+            'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),
+            'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            'state_string': ('django.db.models.fields.TextField', [], {'default': "''"}),
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'symmetrical': 'False', 'to': "orm['forum.Tag']"}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})
+        },
+        'forum.noderevision': {
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),
+            'body': ('django.db.models.fields.TextField', [], {}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})
+        },
+        'forum.nodestate': {
+            'Meta': {'unique_together': "(('node', 'state_type'),)", 'object_name': 'NodeState'},
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'node_state'", 'unique': 'True', 'to': "orm['forum.Action']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'states'", 'to': "orm['forum.Node']"}),
+            'state_type': ('django.db.models.fields.CharField', [], {'max_length': '16'})
+        },
+        'forum.openidassociation': {
+            'Meta': {'object_name': 'OpenIdAssociation'},
+            'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}),
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'issued': ('django.db.models.fields.IntegerField', [], {}),
+            'lifetime': ('django.db.models.fields.IntegerField', [], {}),
+            'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}),
+            'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'})
+        },
+        'forum.openidnonce': {
+            'Meta': {'object_name': 'OpenIdNonce'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+            'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
+            'timestamp': ('django.db.models.fields.IntegerField', [], {})
+        },
+        'forum.questionsubscription': {
+            'Meta': {'object_name': 'QuestionSubscription'},
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 7, 1, 13, 6, 46, 789996)'}),
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})
+        },
+        'forum.subscriptionsettings': {
+            'Meta': {'object_name': 'SubscriptionSettings'},
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'send_digest': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})
+        },
+        'forum.tag': {
+            'Meta': {'object_name': 'Tag'},
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'symmetrical': 'False', 'through': "orm['forum.MarkedTag']", 'to': "orm['forum.User']"}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
+        },
+        'forum.user': {
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'symmetrical': 'False', 'through': "orm['forum.QuestionSubscription']", 'to': "orm['forum.Node']"}),
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})
+        },
+        'forum.userproperty': {
+            'Meta': {'unique_together': "(('user', 'key'),)", 'object_name': 'UserProperty'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'properties'", 'to': "orm['forum.User']"}),
+            'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'})
+        },
+        'forum.validationhash': {
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 7, 2, 13, 6, 46, 883626)'}),
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})
+        },
+        'forum.vote': {
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Vote'},
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'vote'", 'unique': 'True', 'to': "orm['forum.Action']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.Node']"}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),
+            'value': ('django.db.models.fields.SmallIntegerField', [], {}),
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})
+        }
+    }
+
+    complete_apps = ['forum']
diff --git a/forum/modules/template_loader.py/forum/migrations/0044_markdown_cache_migration.py b/forum/modules/template_loader.py/forum/migrations/0044_markdown_cache_migration.py
new file mode 100644 (file)
index 0000000..ac31742
--- /dev/null
@@ -0,0 +1,271 @@
+# encoding: utf-8
+import os, sys
+import datetime
+from south.db import db
+from south.v2 import DataMigration
+from django.db import models
+from forum.migrations import ProgressBar
+
+import markdown
+from django.utils.safestring import mark_safe
+from django.utils.html import strip_tags
+from forum.utils.html import sanitize_html
+
+class Migration(DataMigration):
+
+    def forwards(self, orm):
+        sys.path.append(os.path.join(os.path.dirname(__file__),'../markdownext'))
+
+        count  = orm.Node.objects.count()
+        progress = ProgressBar(count)
+        
+        for node in orm.Node.objects.all():
+            rev = node.active_revision
+
+            if not rev:
+                try:
+                    rev = node.revisions.order_by('-revision')[0]
+                except:
+                    continue
+            node.body = sanitize_html(markdown.markdown(rev.body, ['urlize']))
+            node.save()
+            progress.update()
+
+    def backwards(self, orm):
+        "Write your backwards methods here."
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'forum.action': {
+            'Meta': {'object_name': 'Action'},
+            'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
+            'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}),
+            'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+            'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}),
+            'real_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'proxied_actions'", 'null': 'True', 'to': "orm['forum.User']"}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"})
+        },
+        'forum.actionrepute': {
+            'Meta': {'object_name': 'ActionRepute'},
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}),
+            'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),
+            'value': ('django.db.models.fields.IntegerField', [], {'default': '0'})
+        },
+        'forum.authkeyuserassociation': {
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})
+        },
+        'forum.award': {
+            'Meta': {'unique_together': "(('user', 'badge', 'node'),)", 'object_name': 'Award'},
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'award'", 'unique': 'True', 'to': "orm['forum.Action']"}),
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.Badge']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),
+            'trigger': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'null': 'True', 'to': "orm['forum.Action']"}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})
+        },
+        'forum.badge': {
+            'Meta': {'object_name': 'Badge'},
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'symmetrical': 'False', 'through': "orm['forum.Award']", 'to': "orm['forum.User']"}),
+            'cls': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})
+        },
+        'forum.flag': {
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Flag'},
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'flag'", 'unique': 'True', 'to': "orm['forum.Action']"}),
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flags'", 'to': "orm['forum.Node']"}),
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flags'", 'to': "orm['forum.User']"})
+        },
+        'forum.keyvalue': {
+            'Meta': {'object_name': 'KeyValue'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+            'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'})
+        },
+        'forum.markedtag': {
+            'Meta': {'object_name': 'MarkedTag'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})
+        },
+        'forum.node': {
+            'Meta': {'object_name': 'Node'},
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),
+            'body': ('django.db.models.fields.TextField', [], {}),
+            'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}),
+            'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),
+            'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),
+            'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            'state_string': ('django.db.models.fields.TextField', [], {'default': "''"}),
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'symmetrical': 'False', 'to': "orm['forum.Tag']"}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})
+        },
+        'forum.noderevision': {
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),
+            'body': ('django.db.models.fields.TextField', [], {}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})
+        },
+        'forum.nodestate': {
+            'Meta': {'unique_together': "(('node', 'state_type'),)", 'object_name': 'NodeState'},
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'node_state'", 'unique': 'True', 'to': "orm['forum.Action']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'states'", 'to': "orm['forum.Node']"}),
+            'state_type': ('django.db.models.fields.CharField', [], {'max_length': '16'})
+        },
+        'forum.questionsubscription': {
+            'Meta': {'object_name': 'QuestionSubscription'},
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 12, 22, 17, 54, 20, 862306)'}),
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})
+        },
+        'forum.subscriptionsettings': {
+            'Meta': {'object_name': 'SubscriptionSettings'},
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'send_digest': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})
+        },
+        'forum.tag': {
+            'Meta': {'object_name': 'Tag'},
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'symmetrical': 'False', 'through': "orm['forum.MarkedTag']", 'to': "orm['forum.User']"}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
+        },
+        'forum.user': {
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'symmetrical': 'False', 'through': "orm['forum.QuestionSubscription']", 'to': "orm['forum.Node']"}),
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})
+        },
+        'forum.userproperty': {
+            'Meta': {'unique_together': "(('user', 'key'),)", 'object_name': 'UserProperty'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'properties'", 'to': "orm['forum.User']"}),
+            'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'})
+        },
+        'forum.validationhash': {
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 12, 23, 17, 54, 20, 937539)'}),
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})
+        },
+        'forum.vote': {
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Vote'},
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'vote'", 'unique': 'True', 'to': "orm['forum.Action']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.Node']"}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),
+            'value': ('django.db.models.fields.SmallIntegerField', [], {}),
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})
+        }
+    }
+
+    complete_apps = ['forum']
diff --git a/forum/modules/template_loader.py/forum/migrations/__init__.py b/forum/modules/template_loader.py/forum/migrations/__init__.py
new file mode 100644 (file)
index 0000000..01fd2df
--- /dev/null
@@ -0,0 +1,16 @@
+import sys\r
+\r
+class ProgressBar(object):\r
+    def __init__(self, full):\r
+        self.full = full\r
+        self.count = 0\r
+\r
+        self.print_bar(0)\r
+\r
+    def print_bar(self, progress):\r
+        sys.stdout.write("[%s%s] %d%%\r" % ('=' * progress, ' ' * (100 - progress), progress))\r
+        sys.stdout.flush()\r
+\r
+    def update(self):\r
+        self.count += 1\r
+        self.print_bar(int((float(self.count) / float(self.full)) * 100))
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/models/__init__.py b/forum/modules/template_loader.py/forum/models/__init__.py
new file mode 100644 (file)
index 0000000..2164e36
--- /dev/null
@@ -0,0 +1,39 @@
+import forum.utils.djangofix
+from question import Question ,QuestionRevision, QuestionSubscription
+from answer import Answer, AnswerRevision
+from tag import Tag, MarkedTag
+from user import User, ValidationHash, AuthKeyUserAssociation, SubscriptionSettings
+from node import Node, NodeRevision, NodeState, NodeMetaClass
+from comment import Comment
+from action import Action, ActionRepute
+from meta import Vote, Flag, Badge, Award
+from utils import KeyValue
+from page import Page
+
+try:
+    from south.modelsinspector import add_introspection_rules
+    add_introspection_rules([], [r"^forum\.models\.\w+\.\w+"])
+except:
+    pass
+
+from base import *
+
+__all__ = [
+        'Node', 'NodeRevision', 'NodeState',  
+        'Question', 'QuestionSubscription', 'QuestionRevision',
+        'Answer', 'AnswerRevision',
+        'Tag', 'Comment', 'MarkedTag', 'Badge', 'Award',
+        'ValidationHash', 'AuthKeyUserAssociation', 'SubscriptionSettings', 'KeyValue', 'User',
+        'Action', 'ActionRepute', 'Vote', 'Flag', 'Page'
+        ]
+
+
+from forum.modules import get_modules_script_classes
+
+for k, v in get_modules_script_classes('models', models.Model).items():
+    if not k in __all__:
+        __all__.append(k)
+        exec "%s = v" % k
+
+NodeMetaClass.setup_relations()
+BaseMetaClass.setup_denormalizes()
diff --git a/forum/modules/template_loader.py/forum/models/action.py b/forum/modules/template_loader.py/forum/models/action.py
new file mode 100644 (file)
index 0000000..7fd2e6f
--- /dev/null
@@ -0,0 +1,319 @@
+from django.utils.translation import ugettext as _
+from utils import PickledObjectField
+from threading import Thread
+from forum.utils import html
+from base import *
+import re
+
+class ActionQuerySet(CachedQuerySet):
+    def obj_from_datadict(self, datadict):
+        cls = ActionProxyMetaClass.types.get(datadict['action_type'], None)
+        if cls:
+            obj = cls()
+            obj.__dict__.update(datadict)
+            return obj
+        else:
+            return super(ActionQuerySet, self).obj_from_datadict(datadict)
+
+    def get(self, *args, **kwargs):            
+        action = super(ActionQuerySet, self).get(*args, **kwargs).leaf()
+
+        if not isinstance(action, self.model):
+            raise self.model.DoesNotExist()
+
+        return action
+
+class ActionManager(CachedManager):
+    use_for_related_fields = True
+
+    def get_query_set(self):
+        qs = ActionQuerySet(self.model)
+
+        if self.model is not Action:
+            return qs.filter(action_type=self.model.get_type())
+        else:
+            return qs
+
+    def get_for_types(self, types, *args, **kwargs):
+        kwargs['action_type__in'] = [t.get_type() for t in types]
+        return self.get(*args, **kwargs)
+
+
+class Action(BaseModel):
+    user = models.ForeignKey('User', related_name="actions")
+    real_user = models.ForeignKey('User', related_name="proxied_actions", null=True)
+    ip   = models.CharField(max_length=16)
+    node = models.ForeignKey('Node', null=True, related_name="actions")
+    action_type = models.CharField(max_length=16)
+    action_date = models.DateTimeField(default=datetime.datetime.now)
+
+    extra = PickledObjectField()
+
+    canceled = models.BooleanField(default=False)
+    canceled_by = models.ForeignKey('User', null=True, related_name="canceled_actions")
+    canceled_at = models.DateTimeField(null=True)
+    canceled_ip = models.CharField(max_length=16)
+
+    hooks = {}
+
+    objects = ActionManager()
+
+    @property
+    def at(self):
+        return self.action_date
+
+    @property
+    def by(self):
+        return self.user
+
+    def repute_users(self):
+        pass
+
+    def process_data(self, **data):
+        pass
+
+    def process_action(self):
+        pass
+
+    def cancel_action(self):
+        pass
+
+    @property
+    def verb(self):
+        return ""
+
+    def describe(self, viewer=None):
+        return self.__class__.__name__
+
+    def get_absolute_url(self):
+        if self.node:
+            return self.node.get_absolute_url()
+        else:
+            return self.user.get_profile_url()
+
+    def repute(self, user, value):
+        repute = ActionRepute(action=self, user=user, value=value)
+        repute.save()
+        return repute
+
+    def cancel_reputes(self):
+        for repute in self.reputes.all():
+            cancel = ActionRepute(action=self, user=repute.user, value=(-repute.value), by_canceled=True)
+            cancel.save()
+
+    def leaf(self):
+        leaf_cls = ActionProxyMetaClass.types.get(self.action_type, None)
+
+        if leaf_cls is None:
+            return self
+
+        leaf = leaf_cls()
+        d = self._as_dict()
+        leaf.__dict__.update(self._as_dict())
+        l = leaf._as_dict()
+        return leaf
+
+    @classmethod
+    def get_type(cls):
+        return re.sub(r'action$', '', cls.__name__.lower())
+
+    def save(self, data=None, threaded=True, *args, **kwargs):
+        isnew = False
+
+        if not self.id:
+            self.action_type = self.__class__.get_type()
+            isnew = True
+
+        if data:
+            self.process_data(**data)
+
+        super(Action, self).save(*args, **kwargs)
+
+        if isnew:
+            if (self.node is None) or (not self.node.nis.wiki):
+                self.repute_users()
+            self.process_action()
+            self.trigger_hooks(threaded, True)
+
+        return self
+
+    def delete(self, *args, **kwargs):
+        self.cancel_action()
+        super(Action, self).delete(*args, **kwargs)
+
+    def cancel(self, user=None, ip=None):
+        if not self.canceled:
+            self.canceled = True
+            self.canceled_at = datetime.datetime.now()
+            self.canceled_by = (user is None) and self.user or user
+            if ip:
+                self.canceled_ip = ip
+            self.save()
+            self.cancel_reputes()
+            self.cancel_action()
+        #self.trigger_hooks(False)
+
+    @classmethod
+    def get_current(cls, **kwargs):
+        kwargs['canceled'] = False
+
+        try:
+            return cls.objects.get(**kwargs)
+        except cls.MultipleObjectsReturned:
+            logging.error("Got multiple values for action %s with args %s", cls.__name__,
+                          ", ".join(["%s='%s'" % i for i in kwargs.items()]))
+            raise
+        except cls.DoesNotExist:
+            return None
+
+    @classmethod
+    def hook(cls, fn):
+        if not Action.hooks.get(cls, None):
+            Action.hooks[cls] = []
+
+        Action.hooks[cls].append(fn)
+
+    def trigger_hooks(self, threaded, new=True):
+        if threaded:
+            thread = Thread(target=trigger_hooks, args=[self, Action.hooks, new])
+            thread.setDaemon(True)
+            thread.start()
+        else:
+            trigger_hooks(self, Action.hooks, new)
+
+    class Meta:
+        app_label = 'forum'
+
+def trigger_hooks(action, hooks, new):
+    for cls, hooklist in hooks.items():
+        if isinstance(action, cls):
+            for hook in hooklist:
+                try:
+                    hook(action=action, new=new)
+                except Exception, e:
+                    import traceback
+                    logging.error("Error in %s hook: %s" % (cls.__name__, str(e)))
+                    logging.error(traceback.format_exc())
+
+class ActionProxyMetaClass(BaseMetaClass):
+    types = {}
+
+    def __new__(cls, *args, **kwargs):
+        new_cls = super(ActionProxyMetaClass, cls).__new__(cls, *args, **kwargs)
+        cls.types[new_cls.get_type()] = new_cls
+
+        class Meta:
+            proxy = True
+
+        new_cls.Meta = Meta
+        return new_cls
+
+class ActionProxy(Action):
+    __metaclass__ = ActionProxyMetaClass
+
+    def friendly_username(self, viewer, user):
+        return (viewer == user) and _('You') or user.username
+
+    def friendly_ownername(self, owner, user):
+        return (owner == user) and _('your') or user.username
+
+    def viewer_or_user_verb(self, viewer, user, viewer_verb, user_verb):
+        return (viewer == user) and viewer_verb or user_verb
+
+    def hyperlink(self, url, title, **attrs):
+        return html.hyperlink(url, title, **attrs)
+
+    def describe_node(self, viewer, node):
+        node_link = self.hyperlink(node.get_absolute_url(), node.headline)
+
+        if node.parent:
+            node_desc = _("on %(link)s") % {'link': node_link}
+        else:
+            node_desc = node_link
+
+        return _("%(user)s %(node_name)s %(node_desc)s") % {
+        'user': self.hyperlink(node.author.get_profile_url(), self.friendly_ownername(viewer, node.author)),
+        'node_name': node.friendly_name,
+        'node_desc': node_desc,
+        }
+
+    def affected_links(self, viewer):
+        return ", ".join([self.hyperlink(u.get_profile_url(), self.friendly_username(viewer, u)) for u in set([r.user for r in self.reputes.all()])])
+
+    class Meta:
+        proxy = True
+
+class DummyActionProxyMetaClass(type):
+    def __new__(cls, *args, **kwargs):
+        new_cls = super(DummyActionProxyMetaClass, cls).__new__(cls, *args, **kwargs)
+        ActionProxyMetaClass.types[new_cls.get_type()] = new_cls
+        return new_cls
+
+class DummyActionProxy(object):
+    __metaclass__ = DummyActionProxyMetaClass
+
+    hooks = []
+
+    def __init__(self, ip=None):
+        self.ip = ip
+
+    def process_data(self, **data):
+        pass
+
+    def process_action(self):
+        pass
+
+    def save(self, data=None):
+        self.process_action()
+
+        if data:
+            self.process_data(**data)
+
+        for hook in self.__class__.hooks:
+            hook(self, True)
+
+    @classmethod
+    def get_type(cls):
+        return re.sub(r'action$', '', cls.__name__.lower())
+
+    @classmethod
+    def hook(cls, fn):
+        cls.hooks.append(fn)
+
+
+class ActionRepute(models.Model):
+    action = models.ForeignKey(Action, related_name='reputes')
+    date = models.DateTimeField(default=datetime.datetime.now)
+    user = models.ForeignKey('User', related_name='reputes')
+    value = models.IntegerField(default=0)
+    by_canceled = models.BooleanField(default=False)
+
+    @property
+    def positive(self):
+        if self.value > 0: return self.value
+        return 0
+
+    @property
+    def negative(self):
+        if self.value < 0: return self.value
+        return 0
+
+    def _add_to_rep(self, value):
+        if self.user.reputation + value < 0:
+            return 0
+        else:
+            return models.F('reputation') + value
+
+    def save(self, *args, **kwargs):
+        super(ActionRepute, self).save(*args, **kwargs)
+        self.user.reputation = self._add_to_rep(self.value)
+        self.user.save()
+
+    def delete(self):
+        self.user.reputation = self._add_to_rep(-self.value)
+        self.user.save()
+        super(ActionRepute, self).delete()
+
+    class Meta:
+        app_label = 'forum'
+
diff --git a/forum/modules/template_loader.py/forum/models/answer.py b/forum/modules/template_loader.py/forum/models/answer.py
new file mode 100644 (file)
index 0000000..04735a4
--- /dev/null
@@ -0,0 +1,24 @@
+from base import *
+from django.utils.translation import ugettext as _
+
+class Answer(Node):
+    friendly_name = _("answer")
+
+    class Meta(Node.Meta):
+        proxy = True
+
+    @property
+    def accepted(self):
+        return self.nis.accepted
+
+    @property
+    def headline(self):
+        return self.question.headline
+
+    def get_absolute_url(self):
+        return '%s/%s' % (self.question.get_absolute_url(), self.id)
+
+
+class AnswerRevision(NodeRevision):
+    class Meta:
+        proxy = True
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/models/base.py b/forum/modules/template_loader.py/forum/models/base.py
new file mode 100644 (file)
index 0000000..2f934a9
--- /dev/null
@@ -0,0 +1,212 @@
+import datetime
+import re
+from urllib import quote_plus, urlencode
+from django.db import models, IntegrityError, connection, transaction
+from django.utils.http import urlquote  as django_urlquote
+from django.utils.html import strip_tags
+from django.core.urlresolvers import reverse
+from django.contrib.contenttypes import generic
+from django.contrib.contenttypes.models import ContentType
+from django.core.cache import cache
+from django.template.defaultfilters import slugify
+from django.db.models.signals import post_delete, post_save, pre_save, pre_delete
+from django.utils.translation import ugettext as _
+from django.utils.safestring import mark_safe
+from django.contrib.sitemaps import ping_google
+import django.dispatch
+from forum import settings
+import logging
+
+
+class LazyQueryList(object):
+    def __init__(self, model, items):
+        self.model = model
+        self.items = items
+
+    def __getitem__(self, k):
+        return self.model.objects.get(id=self.items[k])
+
+    def __iter__(self):
+        for id in self.items:
+            yield self.model.objects.get(id=id)
+
+    def __len__(self):
+        return len(self.items)
+
+class CachedQuerySet(models.query.QuerySet):
+    def lazy(self):
+        if (not len(self.query.extra)) and (not len(self.query.aggregates)):
+            return LazyQueryList(self.model, list(self.values_list('id', flat=True)))
+        else:
+            return self
+
+    def obj_from_datadict(self, datadict):
+        obj = self.model()
+        obj.__dict__.update(datadict)
+        return obj
+
+    def get(self, *args, **kwargs):
+        key = self.model.infer_cache_key(kwargs)
+
+        if key is not None:
+            obj = cache.get(key)
+
+            if obj is None:
+                obj = super(CachedQuerySet, self).get(*args, **kwargs)
+                obj.cache()
+            else:
+                obj = self.obj_from_datadict(obj)
+                obj.reset_original_state()
+
+            return obj
+
+        return super(CachedQuerySet, self).get(*args, **kwargs) 
+
+class CachedManager(models.Manager):
+    use_for_related_fields = True
+
+    def get_query_set(self):
+        return CachedQuerySet(self.model)
+
+    def get_or_create(self, *args, **kwargs):
+        try:
+            return self.get(*args, **kwargs)
+        except:
+            return super(CachedManager, self).get_or_create(*args, **kwargs)
+
+
+class DenormalizedField(object):
+    def __init__(self, manager, *args, **kwargs):
+        self.manager = manager
+        self.filter = (args, kwargs)
+
+    def setup_class(self, cls, name):
+        dict_name = '_%s_dencache_' % name
+
+        def getter(inst):
+            val = inst.__dict__.get(dict_name, None)
+
+            if val is None:
+                val = getattr(inst, self.manager).filter(*self.filter[0], **self.filter[1]).count()
+                inst.__dict__[dict_name] = val
+                inst.cache()
+
+            return val
+
+        def reset_cache(inst):
+            inst.__dict__.pop(dict_name, None)
+            inst.uncache()
+
+        cls.add_to_class(name, property(getter))
+        cls.add_to_class("reset_%s_cache" % name, reset_cache)
+
+
+class BaseMetaClass(models.Model.__metaclass__):
+    to_denormalize = []
+
+    def __new__(cls, *args, **kwargs):
+        new_cls = super(BaseMetaClass, cls).__new__(cls, *args, **kwargs)
+
+        BaseMetaClass.to_denormalize.extend(
+            [(new_cls, name, field) for name, field in new_cls.__dict__.items() if isinstance(field, DenormalizedField)]
+        )
+
+        return new_cls
+
+    @classmethod
+    def setup_denormalizes(cls):
+        for new_cls, name, field in BaseMetaClass.to_denormalize:
+            field.setup_class(new_cls, name)
+
+
+class BaseModel(models.Model):
+    __metaclass__ = BaseMetaClass
+
+    objects = CachedManager()
+
+    class Meta:
+        abstract = True
+        app_label = 'forum'
+
+    def __init__(self, *args, **kwargs):
+        super(BaseModel, self).__init__(*args, **kwargs)
+        self.reset_original_state(kwargs.keys())
+
+    def reset_original_state(self, reset_fields=None):
+        self._original_state = self._as_dict()
+        
+        if reset_fields:
+            self._original_state.update(dict([(f, None) for f in reset_fields]))
+
+    def get_dirty_fields(self):
+        return [f.name for f in self._meta.fields if self._original_state[f.attname] != self.__dict__[f.attname]]
+
+    def _as_dict(self):
+        return dict([(name, getattr(self, name)) for name in
+                     ([f.attname for f in self._meta.fields] + [k for k in self.__dict__.keys() if k.endswith('_dencache_')])
+        ])
+
+    def _get_update_kwargs(self):
+        return dict([
+            (f.name, getattr(self, f.name)) for f in self._meta.fields if self._original_state[f.attname] != self.__dict__[f.attname]
+        ])
+
+    def save(self, full_save=False, *args, **kwargs):
+        put_back = [k for k, v in self.__dict__.items() if isinstance(v, models.expressions.ExpressionNode)]
+
+        if self.id and not full_save:
+            self.__class__.objects.filter(id=self.id).update(**self._get_update_kwargs())
+        else:
+            super(BaseModel, self).save()
+
+        if put_back:
+            try:
+                self.__dict__.update(
+                    self.__class__.objects.filter(id=self.id).values(*put_back)[0]
+                )
+            except:
+                logging.error("Unable to read %s from %s" % (", ".join(put_back), self.__class__.__name__))
+                self.uncache()
+
+        self.reset_original_state()
+        self.cache()
+
+    @classmethod
+    def _generate_cache_key(cls, key, group=None):
+        if group is None:
+            group = cls.__name__
+
+        return '%s:%s:%s' % (settings.APP_URL, group, key)
+
+    def cache_key(self):
+        return self._generate_cache_key(self.id)
+
+    @classmethod
+    def infer_cache_key(cls, querydict):
+        try:
+            pk = [v for (k,v) in querydict.items() if k in ('pk', 'pk__exact', 'id', 'id__exact'
+                            ) or k.endswith('_ptr__pk') or k.endswith('_ptr__id')][0]
+
+            return cls._generate_cache_key(pk)
+        except:
+            return None
+
+    def cache(self):
+        cache.set(self.cache_key(), self._as_dict(), 60 * 60)
+
+    def uncache(self):
+        cache.delete(self.cache_key())
+
+    def delete(self):
+        self.uncache()
+        super(BaseModel, self).delete()
+
+
+from user import User
+from node import Node, NodeRevision, NodeManager
+from action import Action
+
+
+
+
+
diff --git a/forum/modules/template_loader.py/forum/models/comment.py b/forum/modules/template_loader.py/forum/models/comment.py
new file mode 100644 (file)
index 0000000..b62e7b5
--- /dev/null
@@ -0,0 +1,58 @@
+from base import *
+from django.utils.translation import ugettext as _
+import re
+
+class Comment(Node):
+    friendly_name = _("comment")
+
+    class Meta(Node.Meta):
+        ordering = ('-added_at',)
+        proxy = True
+
+    def _update_parent_comment_count(self, diff):
+        parent = self.parent
+        parent.comment_count = parent.comment_count + diff
+        parent.save()
+
+    @property
+    def comment(self):
+        if settings.FORM_ALLOW_MARKDOWN_IN_COMMENTS:
+            return self.as_markdown('limitedsyntax')
+        else:
+            return self.body
+
+    @property
+    def headline(self):
+        return self.absolute_parent.headline
+
+    @property
+    def content_object(self):
+        return self.parent.leaf
+
+    def save(self, *args, **kwargs):
+        super(Comment,self).save(*args, **kwargs)
+
+        if not self.id:
+            self.parent.reset_comment_count_cache()
+
+    def mark_deleted(self, user):
+        if super(Comment, self).mark_deleted(user):
+            self.parent.reset_comment_count_cache()
+
+    def unmark_deleted(self):
+        if super(Comment, self).unmark_deleted():
+            self.parent.reset_comment_count_cache()
+
+    def is_reply_to(self, user):
+        inreply = re.search('@\w+', self.body)
+        if inreply is not None:
+            return user.username.startswith(inreply.group(0))
+
+        return False
+
+    def get_absolute_url(self):
+        return self.abs_parent.get_absolute_url() + "#%d" % self.id
+
+    def __unicode__(self):
+        return self.body
+
diff --git a/forum/modules/template_loader.py/forum/models/meta.py b/forum/modules/template_loader.py/forum/models/meta.py
new file mode 100644 (file)
index 0000000..41dc5d6
--- /dev/null
@@ -0,0 +1,99 @@
+from django.utils.translation import ugettext as _
+from base import *
+
+class Vote(models.Model):
+    user = models.ForeignKey(User, related_name="votes")
+    node = models.ForeignKey(Node, related_name="votes")
+    value = models.SmallIntegerField()
+    action = models.OneToOneField(Action, related_name="vote")
+    voted_at = models.DateTimeField(default=datetime.datetime.now)
+
+    class Meta:
+        app_label = 'forum'
+        unique_together = ('user', 'node')
+
+
+class Flag(models.Model):
+    user = models.ForeignKey(User, related_name="flags")
+    node = models.ForeignKey(Node, related_name="flags")
+    reason = models.CharField(max_length=300)
+    action = models.OneToOneField(Action, related_name="flag")
+    flagged_at = models.DateTimeField(default=datetime.datetime.now)
+
+    class Meta:
+        app_label = 'forum'
+        unique_together = ('user', 'node')
+
+class BadgesQuerySet(models.query.QuerySet):
+    def get(self, *args, **kwargs):
+        try:
+            pk = [v for (k,v) in kwargs.items() if k in ('pk', 'pk__exact', 'id', 'id__exact')][0]
+        except:
+            return super(BadgesQuerySet, self).get(*args, **kwargs)
+
+        from forum.badges.base import BadgesMeta
+        badge = BadgesMeta.by_id.get(int(pk), None)
+        if not badge:
+            return super(BadgesQuerySet, self).get(*args, **kwargs)
+        return badge.ondb
+
+
+class BadgeManager(models.Manager):
+    use_for_related_fields = True
+
+    def get_query_set(self):
+        return BadgesQuerySet(self.model)
+
+class Badge(models.Model):
+    GOLD = 1
+    SILVER = 2
+    BRONZE = 3
+
+    type        = models.SmallIntegerField()
+    cls         = models.CharField(max_length=50, null=True)
+    awarded_count = models.PositiveIntegerField(default=0)
+    
+    awarded_to    = models.ManyToManyField(User, through='Award', related_name='badges')
+
+    objects = BadgeManager()
+
+    @property
+    def name(self):
+        cls = self.__dict__.get('_class', None)
+        return cls and cls.name or _("Unknown")
+
+    @property
+    def description(self):
+        cls = self.__dict__.get('_class', None)
+        return cls and cls.description or _("No description available")
+
+    @models.permalink
+    def get_absolute_url(self):
+        return ('badge', [], {'id': self.id, 'slug': slugify(self.name)})
+
+    def save(self, *args, **kwargs):
+        if isinstance(self.awarded_count, models.expressions.ExpressionNode):
+            super(Badge, self).save(*args, **kwargs)
+            self.awarded_count = self.__class__.objects.filter(id=self.id).values_list('awarded_count', flat=True)[0]
+        else:
+            super(Badge, self).save(*args, **kwargs)
+
+
+    class Meta:
+        app_label = 'forum'
+
+
+class Award(models.Model):
+    user = models.ForeignKey(User)
+    badge = models.ForeignKey('Badge', related_name="awards")
+    node = models.ForeignKey(Node, null=True)
+
+    awarded_at = models.DateTimeField(default=datetime.datetime.now)
+
+    trigger = models.ForeignKey(Action, related_name="awards", null=True)
+    action = models.OneToOneField(Action, related_name="award")
+
+
+    class Meta:
+        unique_together = ('user', 'badge', 'node')
+        app_label = 'forum'
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/models/node.py b/forum/modules/template_loader.py/forum/models/node.py
new file mode 100644 (file)
index 0000000..ebe9139
--- /dev/null
@@ -0,0 +1,465 @@
+from base import *
+import re
+from tag import Tag
+
+import markdown
+from django.utils.translation import ugettext as _
+from django.utils.safestring import mark_safe
+from django.utils.html import strip_tags
+from forum.utils.html import sanitize_html
+from utils import PickledObjectField
+
+class NodeContent(models.Model):
+    title      = models.CharField(max_length=300)
+    tagnames   = models.CharField(max_length=125)
+    author     = models.ForeignKey(User, related_name='%(class)ss')
+    body       = models.TextField()
+
+    @property
+    def user(self):
+        return self.author
+
+    @property
+    def html(self):
+        return self.body
+
+    @classmethod
+    def _as_markdown(cls, content, *extensions):
+        try:
+            return mark_safe(sanitize_html(markdown.markdown(content, extensions=extensions)))
+        except Exception, e:
+            import traceback
+            logging.error("Caught exception %s in markdown parser rendering %s %s:\s %s" % (
+                str(e), cls.__name__, str(e), traceback.format_exc()))
+            return ''
+
+    def as_markdown(self, *extensions):
+        return self._as_markdown(self.body, *extensions)
+
+    @property
+    def headline(self):
+        return self.title
+
+    def tagname_list(self):
+        if self.tagnames:
+            t = [name.strip() for name in self.tagnames.split(u' ') if name]
+            return [name.strip() for name in self.tagnames.split(u' ') if name]
+        else:
+            return []
+
+    def tagname_meta_generator(self):
+        return u','.join([tag for tag in self.tagname_list()])
+
+    class Meta:
+        abstract = True
+        app_label = 'forum'
+
+class NodeMetaClass(BaseMetaClass):
+    types = {}
+
+    def __new__(cls, *args, **kwargs):
+        new_cls = super(NodeMetaClass, cls).__new__(cls, *args, **kwargs)
+
+        if not new_cls._meta.abstract and new_cls.__name__ is not 'Node':
+            NodeMetaClass.types[new_cls.get_type()] = new_cls
+
+        return new_cls
+
+    @classmethod
+    def setup_relations(cls):
+        for node_cls in NodeMetaClass.types.values():
+            NodeMetaClass.setup_relation(node_cls)
+
+    @classmethod
+    def setup_relation(cls, node_cls):
+        name = node_cls.__name__.lower()
+
+        def children(self):
+            return node_cls.objects.filter(parent=self)
+
+        def parent(self):
+            if (self.parent is not None) and self.parent.node_type == name:
+                return self.parent.leaf
+
+            return None
+
+        Node.add_to_class(name + 's', property(children))
+        Node.add_to_class(name, property(parent))
+
+
+class NodeQuerySet(CachedQuerySet):
+    def obj_from_datadict(self, datadict):
+        cls = NodeMetaClass.types.get(datadict.get("node_type", ""), None)
+        if cls:
+            obj = cls()
+            obj.__dict__.update(datadict)
+            return obj
+        else:
+            return super(NodeQuerySet, self).obj_from_datadict(datadict)
+
+    def get(self, *args, **kwargs):
+        node = super(NodeQuerySet, self).get(*args, **kwargs).leaf
+
+        if not isinstance(node, self.model):
+            raise self.model.DoesNotExist()
+
+        return node
+
+    def any_state(self, *args):
+        filter = None
+
+        for s in args:
+            s_filter = models.Q(state_string__contains="(%s)" % s)
+            filter = filter and (filter | s_filter) or s_filter
+
+        if filter:
+            return self.filter(filter)
+        else:
+            return self
+
+    def all_states(self, *args):
+        filter = None
+
+        for s in args:
+            s_filter = models.Q(state_string__contains="(%s)" % s)
+            filter = filter and (filter & s_filter) or s_filter
+
+        if filter:
+            return self.filter(filter)
+        else:
+            return self
+
+    def filter_state(self, **kwargs):
+        apply_bool = lambda q, b: b and q or ~q
+        return self.filter(*[apply_bool(models.Q(state_string__contains="(%s)" % s), b) for s, b in kwargs.items()])
+
+    def children_count(self, child_type):
+        return NodeMetaClass.types[child_type].objects.filter_state(deleted=False).filter(parent__in=self).count()
+
+
+class NodeManager(CachedManager):
+    use_for_related_fields = True
+
+    def get_query_set(self):
+        qs = NodeQuerySet(self.model)
+
+        if self.model is not Node:
+            return qs.filter(node_type=self.model.get_type())
+        else:
+            return qs
+
+    def get_for_types(self, types, *args, **kwargs):
+        kwargs['node_type__in'] = [t.get_type() for t in types]
+        return self.get(*args, **kwargs)
+
+    def filter_state(self, **kwargs):
+        return self.all().filter_state(**kwargs)
+
+
+class NodeStateDict(object):
+    def __init__(self, node):
+        self.__dict__['_node'] = node
+
+    def __getattr__(self, name):
+        if self.__dict__.get(name, None):
+            return self.__dict__[name]
+
+        try:
+            node = self.__dict__['_node']
+            action = NodeState.objects.get(node=node, state_type=name).action
+            self.__dict__[name] = action
+            return action
+        except:
+            return None
+
+    def __setattr__(self, name, value):
+        current = self.__getattr__(name)
+
+        if value:
+            if current:
+                current.action = value
+                current.save()
+            else:
+                node = self.__dict__['_node']
+                state = NodeState(node=node, action=value, state_type=name)
+                state.save()
+                self.__dict__[name] = value
+
+                if not "(%s)" % name in node.state_string:
+                    node.state_string = "%s(%s)" % (node.state_string, name)
+                    node.save()
+        else:
+            if current:
+                node = self.__dict__['_node']
+                node.state_string = "".join("(%s)" % s for s in re.findall('\w+', node.state_string) if s != name)
+                node.save()
+                current.node_state.delete()
+                del self.__dict__[name]
+
+
+class NodeStateQuery(object):
+    def __init__(self, node):
+        self.__dict__['_node'] = node
+
+    def __getattr__(self, name):
+        node = self.__dict__['_node']
+        return "(%s)" % name in node.state_string
+
+
+class Node(BaseModel, NodeContent):
+    __metaclass__ = NodeMetaClass
+
+    node_type            = models.CharField(max_length=16, default='node')
+    parent               = models.ForeignKey('Node', related_name='children', null=True)
+    abs_parent           = models.ForeignKey('Node', related_name='all_children', null=True)
+
+    added_at             = models.DateTimeField(default=datetime.datetime.now)
+    score                 = models.IntegerField(default=0)
+
+    state_string          = models.TextField(default='')
+    last_edited           = models.ForeignKey('Action', null=True, unique=True, related_name="edited_node")
+
+    last_activity_by       = models.ForeignKey(User, null=True)
+    last_activity_at       = models.DateTimeField(null=True, blank=True)
+
+    tags                 = models.ManyToManyField('Tag', related_name='%(class)ss')
+    active_revision       = models.OneToOneField('NodeRevision', related_name='active', null=True)
+
+    extra = PickledObjectField()
+    extra_ref = models.ForeignKey('Node', null=True)
+    extra_count = models.IntegerField(default=0)
+
+    marked = models.BooleanField(default=False)
+
+    comment_count = DenormalizedField("children", node_type="comment", canceled=False)
+    flag_count = DenormalizedField("flags")
+
+    friendly_name = _("post")
+
+    objects = NodeManager()
+
+    def __unicode__(self):
+        return self.headline
+
+    @classmethod
+    def _generate_cache_key(cls, key, group="node"):
+        return super(Node, cls)._generate_cache_key(key, group)
+        
+    @classmethod
+    def get_type(cls):
+        return cls.__name__.lower()
+
+    @property
+    def leaf(self):
+        leaf_cls = NodeMetaClass.types.get(self.node_type, None)
+
+        if leaf_cls is None:
+            return self
+
+        leaf = leaf_cls()
+        leaf.__dict__ = self.__dict__
+        return leaf
+
+    @property
+    def nstate(self):
+        state = self.__dict__.get('_nstate', None)
+
+        if state is None:
+            state = NodeStateDict(self)
+            self._nstate = state
+
+        return state
+
+    @property
+    def nis(self):
+        nis = self.__dict__.get('_nis', None)
+
+        if nis is None:
+            nis = NodeStateQuery(self)
+            self._nis = nis
+
+        return nis
+
+    @property
+    def last_activity(self):
+        try:
+            return self.actions.order_by('-action_date')[0].action_date
+        except:
+            return self.last_seen
+
+    @property
+    def state_list(self):
+        return [s.state_type for s in self.states.all()]
+
+    @property
+    def deleted(self):
+        return self.nis.deleted
+
+    @property
+    def absolute_parent(self):
+        if not self.abs_parent_id:
+            return self
+
+        return self.abs_parent
+
+    @property
+    def summary(self):
+        return strip_tags(self.html)[:300]
+
+    @models.permalink
+    def get_revisions_url(self):
+        return ('revisions', (), {'id': self.id})
+
+    def update_last_activity(self, user, save=False, time=None):
+        if not time:
+            time = datetime.datetime.now()
+
+        self.last_activity_by = user
+        self.last_activity_at = time
+
+        if self.parent:
+            self.parent.update_last_activity(user, save=True, time=time)
+
+        if save:
+            self.save()
+
+    def _create_revision(self, user, number, **kwargs):
+        revision = NodeRevision(author=user, revision=number, node=self, **kwargs)
+        revision.save()
+        return revision
+
+    def create_revision(self, user, **kwargs):
+        number = self.revisions.aggregate(last=models.Max('revision'))['last'] + 1
+        revision = self._create_revision(user, number, **kwargs)
+        self.activate_revision(user, revision, extensions=['urlize'])
+        return revision
+
+    def activate_revision(self, user, revision, extensions=['urlize']):
+        self.title = revision.title
+        self.tagnames = revision.tagnames
+        
+        from forum.utils.userlinking import auto_user_link
+        
+        self.body = auto_user_link(self, self._as_markdown(revision.body, *extensions))
+
+        self.active_revision = revision
+        self.update_last_activity(user)
+
+        self.save()
+
+    def _list_changes_in_tags(self):
+        dirty = self.get_dirty_fields()
+
+        if not 'tagnames' in dirty:
+            return None
+        else:
+            if self._original_state['tagnames']:
+                old_tags = set(name for name in self._original_state['tagnames'].split(u' '))
+            else:
+                old_tags = set()
+            new_tags = set(name for name in self.tagnames.split(u' ') if name)
+
+            return dict(
+                    current=list(new_tags),
+                    added=list(new_tags - old_tags),
+                    removed=list(old_tags - new_tags)
+                    )
+
+    def _last_active_user(self):
+        return self.last_edited and self.last_edited.by or self.author
+
+    def _process_changes_in_tags(self):
+        tag_changes = self._list_changes_in_tags()
+
+        if tag_changes is not None:
+            for name in tag_changes['added']:
+                try:
+                    tag = Tag.objects.get(name=name)
+                except:
+                    tag = Tag.objects.create(name=name, created_by=self._last_active_user())
+
+                if not self.nis.deleted:
+                    tag.add_to_usage_count(1)
+                    tag.save()
+
+            if not self.nis.deleted:
+                for name in tag_changes['removed']:
+                    try:
+                        tag = Tag.objects.get(name=name)
+                        tag.add_to_usage_count(-1)
+                        tag.save()
+                    except:
+                        pass
+
+            return True
+
+        return False
+
+    def mark_deleted(self, action):
+        self.nstate.deleted = action
+        self.save()
+
+        if action:
+            for tag in self.tags.all():
+                tag.add_to_usage_count(-1)
+                tag.save()
+        else:
+            for tag in Tag.objects.filter(name__in=self.tagname_list()):
+                tag.add_to_usage_count(1)
+                tag.save()
+
+    def delete(self, *args, **kwargs):
+        self.active_revision = None
+        self.save()
+
+        for n in self.children.all():
+            n.delete()
+
+        for a in self.actions.all():
+            a.cancel()
+
+        super(Node, self).delete(*args, **kwargs)
+
+    def save(self, *args, **kwargs):
+        if not self.id:
+            self.node_type = self.get_type()
+            super(BaseModel, self).save(*args, **kwargs)
+            self.active_revision = self._create_revision(self.author, 1, title=self.title, tagnames=self.tagnames,
+                                                         body=self.body)
+            self.activate_revision(self.author, self.active_revision)
+            self.update_last_activity(self.author, time=self.added_at)
+
+        if self.parent_id and not self.abs_parent_id:
+            self.abs_parent = self.parent.absolute_parent
+        
+        tags_changed = self._process_changes_in_tags()
+        
+        super(Node, self).save(*args, **kwargs)
+        
+        if tags_changed: self.tags = list(Tag.objects.filter(name__in=self.tagname_list()))
+
+    class Meta:
+        app_label = 'forum'
+
+
+class NodeRevision(BaseModel, NodeContent):
+    node       = models.ForeignKey(Node, related_name='revisions')
+    summary    = models.CharField(max_length=300)
+    revision   = models.PositiveIntegerField()
+    revised_at = models.DateTimeField(default=datetime.datetime.now)
+
+    class Meta:
+        unique_together = ('node', 'revision')
+        app_label = 'forum'
+
+
+class NodeState(models.Model):
+    node       = models.ForeignKey(Node, related_name='states')
+    state_type = models.CharField(max_length=16)
+    action     = models.OneToOneField('Action', related_name="node_state")
+
+    class Meta:
+        unique_together = ('node', 'state_type')
+        app_label = 'forum'
+
+
diff --git a/forum/modules/template_loader.py/forum/models/page.py b/forum/modules/template_loader.py/forum/models/page.py
new file mode 100644 (file)
index 0000000..665a1be
--- /dev/null
@@ -0,0 +1,54 @@
+from base import *
+from django.utils.translation import ugettext as _
+
+class Page(Node):
+    friendly_name = _("page")
+
+    @property
+    def published(self):
+        return self.marked
+
+    @property
+    def html(self):
+        return self._as_markdown(self.body)
+
+    def save(self, *args, **kwargs):
+        old_options = self._original_state.get('extra', None)
+
+        super(Page, self).save(*args, **kwargs)
+
+        registry = settings.STATIC_PAGE_REGISTRY
+
+        if old_options:
+            registry.pop(old_options.get('path', ''), None)
+
+        registry[self.extra['path']] = self.id
+
+
+        settings.STATIC_PAGE_REGISTRY.set_value(registry)
+
+    @property
+    def headline(self):
+        if self.published:
+            return self.title
+        else:
+            return _("[Unpublished] %s") % self.title
+
+    @models.permalink
+    def get_absolute_url(self):
+        return ('static_page', (), {'path': self.extra['path']})
+        
+    def activate_revision(self, user, revision, extensions=['urlize']):
+        self.title = revision.title
+        self.tagnames = revision.tagnames        
+        self.body = revision.body
+
+        self.active_revision = revision
+        self.update_last_activity(user)
+
+        self.save()
+
+    class Meta(Node.Meta):
+        proxy = True
+
+    
diff --git a/forum/modules/template_loader.py/forum/models/question.py b/forum/modules/template_loader.py/forum/models/question.py
new file mode 100644 (file)
index 0000000..bef5bb5
--- /dev/null
@@ -0,0 +1,101 @@
+from base import *
+from tag import Tag
+from django.utils.translation import ugettext as _
+
+question_view = django.dispatch.Signal(providing_args=['instance', 'user'])
+
+class QuestionManager(NodeManager):
+    def search(self, keywords):
+        return False, self.filter(models.Q(title__icontains=keywords) | models.Q(body__icontains=keywords))
+
+class Question(Node):
+    class Meta(Node.Meta):
+        proxy = True
+
+    answer_count = DenormalizedField("children", ~models.Q(state_string__contains="(deleted)"), node_type="answer")
+    accepted_count = DenormalizedField("children", ~models.Q(state_string__contains="(deleted)"), node_type="answer", marked=True)
+    favorite_count = DenormalizedField("actions", action_type="favorite", canceled=False)
+
+    friendly_name = _("question")
+    objects = QuestionManager()
+
+    @property
+    def closed(self):
+        return self.nis.closed
+
+    @property    
+    def view_count(self):
+        return self.extra_count
+
+    @property
+    def headline(self):
+        if self.nis.deleted:
+            return _('[deleted] ') + self.title
+
+        if self.nis.closed:
+            return _('[closed] ') + self.title
+
+        return self.title
+
+    @property
+    def accepted_answers(self):
+        return self.answers.filter(~models.Q(state_string__contains="(deleted)"), marked=True)
+
+    @models.permalink    
+    def get_absolute_url(self):
+        return ('question', (), {'id': self.id, 'slug': django_urlquote(slugify(self.title))})
+        
+    def meta_description(self):
+        return self.summary
+
+    def get_revision_url(self):
+        return reverse('question_revisions', args=[self.id])
+
+    def get_related_questions(self, count=10):
+        cache_key = '%s.related_questions:%d:%d' % (settings.APP_URL, count, self.id)
+        related_list = cache.get(cache_key)
+
+        if related_list is None:
+            related_list = Question.objects.filter_state(deleted=False).values('id').filter(tags__id__in=[t.id for t in self.tags.all()]
+            ).exclude(id=self.id).annotate(frequency=models.Count('id')).order_by('-frequency')[:count]
+            cache.set(cache_key, related_list, 60 * 60)
+
+        return [Question.objects.get(id=r['id']) for r in related_list]
+    
+    def get_active_users(self):
+        active_users = set()
+        
+        active_users.add(self.author)
+        
+        for answer in self.answers:
+            active_users.add(answer.author)
+            
+            for comment in answer.comments:
+                active_users.add(comment.author)
+                        
+        for comment in self.comments:
+            active_users.add(comment.author)
+        
+        return active_users
+
+def question_viewed(instance, **kwargs):
+    instance.extra_count += 1
+    instance.save()
+
+question_view.connect(question_viewed)
+
+
+class QuestionSubscription(models.Model):
+    user = models.ForeignKey(User)
+    question = models.ForeignKey(Node)
+    auto_subscription = models.BooleanField(default=True)
+    last_view = models.DateTimeField(default=datetime.datetime.now())
+
+    class Meta:
+        app_label = 'forum'
+
+
+class QuestionRevision(NodeRevision):
+    class Meta:
+        proxy = True
+        
diff --git a/forum/modules/template_loader.py/forum/models/tag.py b/forum/modules/template_loader.py/forum/models/tag.py
new file mode 100644 (file)
index 0000000..0bff004
--- /dev/null
@@ -0,0 +1,45 @@
+from base import *
+
+from django.utils.translation import ugettext as _
+import django.dispatch
+
+class ActiveTagManager(models.Manager):
+    def get_query_set(self):
+        return super(ActiveTagManager, self).get_query_set().exclude(used_count__lt=1)
+
+
+class Tag(BaseModel):
+    name            = models.CharField(max_length=255, unique=True)
+    created_by      = models.ForeignKey(User, related_name='created_tags')
+    marked_by       = models.ManyToManyField(User, related_name="marked_tags", through="MarkedTag")
+    # Denormalised data
+    used_count = models.PositiveIntegerField(default=0)
+
+    active = ActiveTagManager()
+
+    class Meta:
+        ordering = ('-used_count', 'name')
+        app_label = 'forum'
+
+    def __unicode__(self):
+        return self.name
+
+    def add_to_usage_count(self, value):
+        if self.used_count + value < 0:
+            self.used_count = 0
+        else:
+            self.used_count = models.F('used_count') + value
+
+    @models.permalink
+    def get_absolute_url(self):
+        return ('tag_questions', (), {'tag': self.name})
+
+class MarkedTag(models.Model):
+    TAG_MARK_REASONS = (('good', _('interesting')), ('bad', _('ignored')))
+    tag = models.ForeignKey(Tag, related_name='user_selections')
+    user = models.ForeignKey(User, related_name='tag_selections')
+    reason = models.CharField(max_length=16, choices=TAG_MARK_REASONS)
+
+    class Meta:
+        app_label = 'forum'
+
diff --git a/forum/modules/template_loader.py/forum/models/tests/__init__.py b/forum/modules/template_loader.py/forum/models/tests/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/forum/modules/template_loader.py/forum/models/tests/fixtures/users b/forum/modules/template_loader.py/forum/models/tests/fixtures/users
new file mode 100644 (file)
index 0000000..7f8a95a
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<django-objects version="1.0">
+    <object pk="100" model="forum.models.user">
+        <field type="CharField" name="username">super</field>
+        <field type="CharField" name="first_name">Super</field>
+        <field type="CharField" name="last_name">User</field>
+        <field type="CharField" name="email">super@example.com</field>
+        <field type="CharField" name="password">sha1$995a3$6011485ea3834267d719b4c801409b8b1ddd0158</field>
+        <field type="BooleanField" name="is_staff">True</field>
+        <field type="BooleanField" name="is_active">True</field>
+        <field type="BooleanField" name="is_superuser">True</field>
+        <field type="DateTimeField" name="last_login">2007-05-30 13:20:10</field>
+        <field type="DateTimeField" name="date_joined">2007-05-30 13:20:10</field>
+        <field to="auth.group" name="groups" rel="ManyToManyRel"></field>
+        <field to="auth.permission" name="user_permissions" rel="ManyToManyRel"></field>
+
+        <field type="BooleanField" name="is_approved">True</field>
+        <field type="BooleanField" name="email_isvalid">True</field>
+        <field type="PositiveIntegerField" name="reputation">10</field>
+        <field type="PositiveIntegerField" name="gold">1</field>
+        <field type="PositiveIntegerField" name="silver">1</field>
+        <field type="PositiveIntegerField" name="bronze">1</field>
+        <field type="DateTimeField" name="last_seen">2007-05-30 13:20:10</field>
+        <field type="CharField" name="real_name">Super User</field>
+        <field type="URLField" name="website">www.superuser.com</field>
+        <field type="CharField" name="location">Raleigh</field>
+        <field type="DateField" name="date_of_birth">2007-05-30 13:20:10</field>
+        <field type="TextField" name="about">I am a super user</field>
+        <field type="ManyToManyField" name="subscriptions"></field>
+        <field type="DenormalizedField" name="vote_up_count">1</field>
+        <field type="DenormalizedField" name="vote_down_count">1</field>
+    </object>
+</django-objects>
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/models/tests/test_user.py b/forum/modules/template_loader.py/forum/models/tests/test_user.py
new file mode 100644 (file)
index 0000000..0d9a93e
--- /dev/null
@@ -0,0 +1,96 @@
+from django.test import TestCase
+from forum.models.user import *
+
+class UserTest(TestCase):
+    fixtures = ['users.xml']
+
+    def setUp(self):
+        self.client.login(username='super', password='secret')
+
+        
+
+    def tearDown(self):
+        self.client.logout()
+
+    def test_gravatar(self):
+        
+        self.assert_(True)
+
+    def test_save(self):
+        self.assert_(True)
+
+    def test_get_absolute_url(self):
+        self.assert_(True)
+
+    def test_get_messages(self):
+        self.assert_(True)
+
+    def test_delete_messages(self):
+        self.assert_(True)
+
+    def test_get_profile_url(self):
+        self.assert_(True)
+
+    def test_get_profile_link(self):
+        self.assert_(True)
+
+    def test_get_visible_answers(self):
+        self.assert_(True)
+
+    def test_get_vote_count_today(self):
+        self.assert_(True)
+
+    def test_get_reputation_by_upvoted_today(self):
+        self.assert_(True)
+
+    def test_get_flagged_items_count_today(self):
+        self.assert_(True)
+
+    def test_can_view_deleted_post(self):
+        self.assert_(True)
+
+    def test_can_vote_up(self):
+        self.assert_(True)
+
+    def test_can_vote_down(self):
+        self.assert_(True)
+
+    def test_can_flag_offensive(self):
+        self.assert_(True)
+
+    def test_can_view_offensive_flags(self):
+        self.assert_(True)
+
+    def test_can_comment(self):
+        self.assert_(True)
+
+    def test_can_like_comment(self):
+        self.assert_(True)
+
+    def test_can_edit_comment(self):
+        self.assert_(True)
+
+    def test_can_delete_comment(self):
+        self.assert_(True)
+
+    def test_can_accept_answer(self):
+        self.assert_(True)
+
+    def test_can_edit_post(self):
+        self.assert_(True)
+
+    def test_can_retag_questions(self):
+        self.assert_(True)
+
+    def test_can_close_question(self):
+        self.assert_(True)
+
+    def test_can_reopen_question(self):
+        self.assert_(True)
+
+    def test_can_delete_post(self):
+        self.assert_(True)
+
+    def test_can_upload_files(self):
+        self.assert_(True)
+
diff --git a/forum/modules/template_loader.py/forum/models/user.py b/forum/modules/template_loader.py/forum/models/user.py
new file mode 100644 (file)
index 0000000..9d63248
--- /dev/null
@@ -0,0 +1,572 @@
+from base import *
+from utils import PickledObjectField
+from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
+from django.contrib.contenttypes.models import ContentType
+from django.contrib.auth.models import User as DjangoUser, AnonymousUser as DjangoAnonymousUser
+from django.db.models import Q
+try:
+    from hashlib import md5
+except:
+    from md5 import new as md5
+
+import string
+from random import Random
+
+from django.utils.translation import ugettext as _
+import logging
+
+QUESTIONS_PER_PAGE_CHOICES = (
+(10, u'10'),
+(30, u'30'),
+(50, u'50'),
+)
+
+class AnonymousUser(DjangoAnonymousUser):
+    reputation = 0
+    
+    def get_visible_answers(self, question):
+        return question.answers.filter_state(deleted=False)
+
+    def can_view_deleted_post(self, post):
+        return False
+
+    def can_vote_up(self):
+        return False
+
+    def can_vote_down(self):
+        return False
+    
+    def can_vote_count_today(self):
+        return 0
+
+    def can_flag_offensive(self, post=None):
+        return False
+
+    def can_view_offensive_flags(self, post=None):
+        return False
+
+    def can_comment(self, post):
+        return False
+
+    def can_like_comment(self, comment):
+        return False
+
+    def can_edit_comment(self, comment):
+        return False
+
+    def can_delete_comment(self, comment):
+        return False
+
+    def can_convert_to_comment(self, answer):
+        return False
+    
+    def can_convert_to_question(self, answer):
+        return False
+    
+    def can_convert_comment_to_answer(self, comment):
+        return False
+
+    def can_accept_answer(self, answer):
+        return False
+
+    def can_create_tags(self):
+        return False
+
+    def can_edit_post(self, post):
+        return False
+
+    def can_wikify(self, post):
+        return False
+
+    def can_cancel_wiki(self, post):
+        return False
+
+    def can_retag_questions(self):
+        return False
+
+    def can_close_question(self, question):
+        return False
+
+    def can_reopen_question(self, question):
+        return False
+
+    def can_delete_post(self, post):
+        return False
+
+    def can_upload_files(self):
+        return False
+
+    def is_a_super_user_or_staff(self):
+        return False
+
+def true_if_is_super_or_staff(fn):
+    def decorated(self, *args, **kwargs):
+        return self.is_superuser or self.is_staff or fn(self, *args, **kwargs)
+
+    return decorated
+
+def false_if_validation_required_to(item):
+    def decorator(fn):
+        def decorated(self, *args, **kwargs):
+            if item in settings.REQUIRE_EMAIL_VALIDATION_TO and not self.email_isvalid:
+                return False
+            else:
+                return fn(self, *args, **kwargs)
+        return decorated
+    return decorator
+
+class User(BaseModel, DjangoUser):
+    is_approved = models.BooleanField(default=False)
+    email_isvalid = models.BooleanField(default=False)
+
+    reputation = models.PositiveIntegerField(default=0)
+    gold = models.PositiveIntegerField(default=0)
+    silver = models.PositiveIntegerField(default=0)
+    bronze = models.PositiveIntegerField(default=0)
+
+    last_seen = models.DateTimeField(default=datetime.datetime.now)
+    real_name = models.CharField(max_length=100, blank=True)
+    website = models.URLField(max_length=200, blank=True)
+    location = models.CharField(max_length=100, blank=True)
+    date_of_birth = models.DateField(null=True, blank=True)
+    about = models.TextField(blank=True)
+
+    subscriptions = models.ManyToManyField('Node', related_name='subscribers', through='QuestionSubscription')
+
+    vote_up_count = DenormalizedField("actions", canceled=False, action_type="voteup")
+    vote_down_count = DenormalizedField("actions", canceled=False, action_type="votedown")
+
+    def __unicode__(self):
+        return self.username
+
+    @property
+    def prop(self):
+        prop = self.__dict__.get('_prop', None)
+
+        if prop is None:
+            prop = UserPropertyDict(self)
+            self._prop = prop
+
+        return prop
+
+    @property
+    def is_siteowner(self):
+        #todo: temporary thing, for now lets just assume that the site owner will always be the first user of the application
+        return self.id == 1
+
+    @property
+    def decorated_name(self):
+        if settings.SHOW_STATUS_DIAMONDS:
+            if self.is_superuser:
+                return u"%s \u2666\u2666" % self.username
+
+            if self.is_staff:
+                return u"%s \u2666" % self.username
+
+        return self.username
+
+    @property
+    def last_activity(self):
+        try:
+            return self.actions.order_by('-action_date')[0].action_date
+        except:
+            return self.last_seen
+
+    @property
+    def gravatar(self):
+        return md5(self.email.lower()).hexdigest()
+    
+    def save(self, *args, **kwargs):
+        if self.reputation < 0:
+            self.reputation = 0
+
+        new = not bool(self.id)
+
+        super(User, self).save(*args, **kwargs)
+
+        if new:
+            sub_settings = SubscriptionSettings(user=self)
+            sub_settings.save()
+
+    def get_absolute_url(self):
+        return self.get_profile_url()
+
+    def get_messages(self):
+        messages = []
+        for m in self.message_set.all():
+            messages.append(m.message)
+        return messages
+
+    def delete_messages(self):
+        self.message_set.all().delete()
+
+    @models.permalink
+    def get_profile_url(self):
+        return ('user_profile', (), {'id': self.id, 'slug': slugify(self.username)})
+
+    def get_absolute_url(self):
+        return self.get_profile_url()
+
+    @models.permalink
+    def get_asked_url(self):
+        return ('user_questions', (), {'mode': _('asked-by'), 'user': self.id, 'slug': slugify(self.username)})
+
+    @models.permalink
+    def get_answered_url(self):
+        return ('user_questions', (), {'mode': _('answered-by'), 'user': self.id, 'slug': slugify(self.username)})
+
+    @models.permalink
+    def get_subscribed_url(self):
+        return ('user_questions', (), {'mode': _('subscribed-by'), 'user': self.id, 'slug': slugify(self.username)})
+
+    def get_profile_link(self):
+        profile_link = u'<a href="%s">%s</a>' % (self.get_profile_url(), self.username)
+        return mark_safe(profile_link)
+
+    def get_visible_answers(self, question):
+        return question.answers.filter_state(deleted=False)
+
+    def get_vote_count_today(self):
+        today = datetime.date.today()
+        return self.actions.filter(canceled=False, action_type__in=("voteup", "votedown"),
+                                   action_date__gte=(today - datetime.timedelta(days=1))).count()
+
+    def get_reputation_by_upvoted_today(self):
+        today = datetime.datetime.now()
+        sum = self.reputes.filter(reputed_at__range=(today - datetime.timedelta(days=1), today)).aggregate(
+                models.Sum('value'))
+        #todo: redo this, maybe transform in the daily cap
+        #if sum.get('value__sum', None) is not None: return sum['value__sum']
+        return 0
+
+    def get_flagged_items_count_today(self):
+        today = datetime.date.today()
+        return self.actions.filter(canceled=False, action_type="flag",
+                                   action_date__gte=(today - datetime.timedelta(days=1))).count()
+    
+    def can_vote_count_today(self):
+        votes_today = settings.MAX_VOTES_PER_DAY
+        
+        if settings.USER_REPUTATION_TO_MAX_VOTES:
+            votes_today = votes_today + int(self.reputation)
+        
+        return votes_today
+    
+    @true_if_is_super_or_staff
+    def can_view_deleted_post(self, post):
+        return post.author == self
+
+    @true_if_is_super_or_staff
+    def can_vote_up(self):
+        return self.reputation >= int(settings.REP_TO_VOTE_UP)
+
+    @true_if_is_super_or_staff
+    def can_vote_down(self):
+        return self.reputation >= int(settings.REP_TO_VOTE_DOWN)
+
+    @false_if_validation_required_to('flag')
+    def can_flag_offensive(self, post=None):
+        if post is not None and post.author == self:
+            return False
+        return self.is_superuser or self.is_staff or self.reputation >= int(settings.REP_TO_FLAG)
+
+    @true_if_is_super_or_staff
+    def can_view_offensive_flags(self, post=None):
+        if post is not None and post.author == self:
+            return True
+        return self.reputation >= int(settings.REP_TO_VIEW_FLAGS)
+
+    @true_if_is_super_or_staff
+    @false_if_validation_required_to('comment')
+    def can_comment(self, post):
+        return self == post.author or self.reputation >= int(settings.REP_TO_COMMENT
+                ) or (post.__class__.__name__ == "Answer" and self == post.question.author)
+
+    @true_if_is_super_or_staff
+    def can_like_comment(self, comment):
+        return self != comment.author and (self.reputation >= int(settings.REP_TO_LIKE_COMMENT))
+
+    @true_if_is_super_or_staff
+    def can_edit_comment(self, comment):
+        return (comment.author == self and comment.added_at >= datetime.datetime.now() - datetime.timedelta(minutes=60)
+        ) or self.is_superuser
+
+    @true_if_is_super_or_staff
+    def can_delete_comment(self, comment):
+        return self == comment.author or self.reputation >= int(settings.REP_TO_DELETE_COMMENTS)
+
+    @true_if_is_super_or_staff
+    def can_convert_comment_to_answer(self, comment):
+        return self == comment.author or self.reputation >= int(settings.REP_TO_CONVERT_COMMENTS_TO_ANSWERS)
+
+    def can_convert_to_comment(self, answer):
+        return (not answer.marked) and (self.is_superuser or self.is_staff or answer.author == self or self.reputation >= int
+                (settings.REP_TO_CONVERT_TO_COMMENT))
+    
+    def can_convert_to_question(self, answer):
+        return (not answer.marked) and (self.is_superuser or self.is_staff or answer.author == self or self.reputation >= int
+                (settings.REP_TO_CONVERT_TO_QUESTION))
+
+    @true_if_is_super_or_staff
+    def can_accept_answer(self, answer):
+        return self == answer.question.author and (settings.USERS_CAN_ACCEPT_OWN or answer.author != answer.question.author)
+
+    @true_if_is_super_or_staff
+    def can_create_tags(self):
+        return self.reputation >= int(settings.REP_TO_CREATE_TAGS)
+
+    @true_if_is_super_or_staff
+    def can_edit_post(self, post):
+        return self == post.author or self.reputation >= int(settings.REP_TO_EDIT_OTHERS
+                                                             ) or (post.nis.wiki and self.reputation >= int(
+                settings.REP_TO_EDIT_WIKI))
+
+    @true_if_is_super_or_staff
+    def can_wikify(self, post):
+        return self == post.author or self.reputation >= int(settings.REP_TO_WIKIFY)
+
+    @true_if_is_super_or_staff
+    def can_cancel_wiki(self, post):
+        return self == post.author
+
+    @true_if_is_super_or_staff
+    def can_retag_questions(self):
+        return self.reputation >= int(settings.REP_TO_RETAG)
+
+    @true_if_is_super_or_staff
+    def can_close_question(self, question):
+        return (self == question.author and self.reputation >= int(settings.REP_TO_CLOSE_OWN)
+        ) or self.reputation >= int(settings.REP_TO_CLOSE_OTHERS)
+
+    @true_if_is_super_or_staff
+    def can_reopen_question(self, question):
+        return self == question.author and self.reputation >= int(settings.REP_TO_REOPEN_OWN)
+
+    @true_if_is_super_or_staff
+    def can_delete_post(self, post):
+        if post.node_type == "comment":
+            return self.can_delete_comment(post)
+
+        return (self == post.author and (post.__class__.__name__ == "Answer" or
+        not post.answers.exclude(author__id=self.id).count()))
+
+    @true_if_is_super_or_staff
+    def can_upload_files(self):
+        return self.reputation >= int(settings.REP_TO_UPLOAD)
+
+    @true_if_is_super_or_staff
+    def is_a_super_user_or_staff(self):
+        return False
+
+    def email_valid_and_can_ask(self):
+        return 'ask' not in settings.REQUIRE_EMAIL_VALIDATION_TO or self.email_isvalid
+
+    def email_valid_and_can_answer(self):
+        return 'answer' not in settings.REQUIRE_EMAIL_VALIDATION_TO or self.email_isvalid
+
+    def check_password(self, old_passwd):
+        self.__dict__.update(self.__class__.objects.filter(id=self.id).values('password')[0])
+        return DjangoUser.check_password(self, old_passwd)
+
+    @property
+    def suspension(self):
+        if self.__dict__.get('_suspension_dencache_', False) != None:
+            try:
+                self.__dict__['_suspension_dencache_'] = self.reputes.get(action__action_type="suspend", action__canceled=False).action
+            except ObjectDoesNotExist:
+                self.__dict__['_suspension_dencache_'] = None
+            except MultipleObjectsReturned:
+                logging.error("Multiple suspension actions found for user %s (%s)" % (self.username, self.id))
+                self.__dict__['_suspension_dencache_'] = self.reputes.filter(action__action_type="suspend", action__canceled=False
+                                                                             ).order_by('-action__action_date')[0]
+
+        return self.__dict__['_suspension_dencache_']
+
+    def _pop_suspension_cache(self):
+        self.__dict__.pop('_suspension_dencache_', None)
+
+    def is_suspended(self):
+        if not self.is_active:
+            suspension = self.suspension
+
+            if suspension and suspension.extra.get('bantype', None) == 'forxdays' and (
+            datetime.datetime.now() > suspension.action_date + datetime.timedelta(
+                    days=int(suspension.extra.get('forxdays', 365)))):
+                suspension.cancel()
+            else:
+                return True
+
+        return False
+
+    class Meta:
+        app_label = 'forum'
+
+class UserProperty(BaseModel):
+    user = models.ForeignKey(User, related_name='properties')
+    key = models.CharField(max_length=16)
+    value = PickledObjectField()
+
+    class Meta:
+        app_label = 'forum'
+        unique_together = ('user', 'key')
+
+    def cache_key(self):
+        return self._generate_cache_key("%s:%s" % (self.user.id, self.key))
+
+    @classmethod
+    def infer_cache_key(cls, querydict):
+        if 'user' in querydict and 'key' in querydict:
+            return cls._generate_cache_key("%s:%s" % (querydict['user'].id, querydict['key']))
+
+        return None
+
+class UserPropertyDict(object):
+    def __init__(self, user):
+        self.__dict__['_user'] = user
+
+    def __get_property(self, name):
+        if self.__dict__.get('__%s__' % name, None):
+            return self.__dict__['__%s__' % name]
+        try:
+            user = self.__dict__['_user']
+            prop = UserProperty.objects.get(user=user, key=name)
+            self.__dict__['__%s__' % name] = prop
+            self.__dict__[name] = prop.value
+            return prop
+        except:
+            return None
+
+
+    def __getattr__(self, name):
+        if self.__dict__.get(name, None):
+            return self.__dict__[name]
+
+        prop = self.__get_property(name)
+
+        if prop:
+            return prop.value
+        else:
+            return None
+
+    def __setattr__(self, name, value):
+        current = self.__get_property(name)
+
+        if value is not None:
+            if current:
+                current.value = value
+                self.__dict__[name] = value
+                current.save(full_save=True)
+            else:
+                user = self.__dict__['_user']
+                prop = UserProperty(user=user, value=value, key=name)
+                prop.save()
+                self.__dict__[name] = value
+                self.__dict__['__%s__' % name] = prop
+        else:
+            if current:
+                current.delete()
+                del self.__dict__[name]
+                del self.__dict__['__%s__' % name]
+
+
+class SubscriptionSettings(models.Model):
+    user = models.OneToOneField(User, related_name='subscription_settings', editable=False)
+
+    enable_notifications = models.BooleanField(default=True)
+
+    #notify if
+    member_joins = models.CharField(max_length=1, default='n')
+    new_question = models.CharField(max_length=1, default='n')
+    new_question_watched_tags = models.CharField(max_length=1, default='i')
+    subscribed_questions = models.CharField(max_length=1, default='i')
+
+    #auto_subscribe_to
+    all_questions = models.BooleanField(default=False)
+    all_questions_watched_tags = models.BooleanField(default=False)
+    questions_asked = models.BooleanField(default=True)
+    questions_answered = models.BooleanField(default=True)
+    questions_commented = models.BooleanField(default=False)
+    questions_viewed = models.BooleanField(default=False)
+
+    #notify activity on subscribed
+    notify_answers = models.BooleanField(default=True)
+    notify_reply_to_comments = models.BooleanField(default=True)
+    notify_comments_own_post = models.BooleanField(default=True)
+    notify_comments = models.BooleanField(default=False)
+    notify_accepted = models.BooleanField(default=False)
+
+    send_digest = models.BooleanField(default=True)
+
+    class Meta:
+        app_label = 'forum'
+
+from forum.utils.time import one_day_from_now
+
+class ValidationHashManager(models.Manager):
+    def _generate_md5_hash(self, user, type, hash_data, seed):
+        return md5("%s%s%s%s" % (seed, "".join(map(str, hash_data)), user.id, type)).hexdigest()
+
+    def create_new(self, user, type, hash_data=[], expiration=None):
+        seed = ''.join(Random().sample(string.letters+string.digits, 12))
+        hash = self._generate_md5_hash(user, type, hash_data, seed)
+
+        obj = ValidationHash(hash_code=hash, seed=seed, user=user, type=type)
+
+        if expiration is not None:
+            obj.expiration = expiration
+
+        try:
+            obj.save()
+        except:
+            return None
+
+        return obj
+
+    def validate(self, hash, user, type, hash_data=[]):
+        try:
+            obj = self.get(hash_code=hash)
+        except:
+            return False
+
+        if obj.type != type:
+            return False
+
+        if obj.user != user:
+            return False
+
+        valid = (obj.hash_code == self._generate_md5_hash(obj.user, type, hash_data, obj.seed))
+
+        if valid:
+            if obj.expiration < datetime.datetime.now():
+                obj.delete()
+                return False
+            else:
+                obj.delete()
+                return True
+
+        return False
+
+class ValidationHash(models.Model):
+    hash_code = models.CharField(max_length=255, unique=True)
+    seed = models.CharField(max_length=12)
+    expiration = models.DateTimeField(default=one_day_from_now)
+    type = models.CharField(max_length=12)
+    user = models.ForeignKey(User)
+
+    objects = ValidationHashManager()
+
+    class Meta:
+        unique_together = ('user', 'type')
+        app_label = 'forum'
+
+    def __str__(self):
+        return self.hash_code
+
+class AuthKeyUserAssociation(models.Model):
+    key = models.CharField(max_length=255, null=False, unique=True)
+    provider = models.CharField(max_length=64)
+    user = models.ForeignKey(User, related_name="auth_keys")
+    added_at = models.DateTimeField(default=datetime.datetime.now)
+
+    class Meta:
+        app_label = 'forum'
diff --git a/forum/modules/template_loader.py/forum/models/utils.py b/forum/modules/template_loader.py/forum/models/utils.py
new file mode 100644 (file)
index 0000000..ecbe038
--- /dev/null
@@ -0,0 +1,124 @@
+from django.db import models
+from django.core.cache import cache
+from django.conf import settings
+from django.utils.encoding import force_unicode
+
+try:
+    from cPickle import loads, dumps
+except ImportError:
+    from pickle import loads, dumps
+
+from copy import deepcopy
+from base64 import b64encode, b64decode
+from zlib import compress, decompress
+import re
+
+from base import BaseModel
+
+MAX_MARKABLE_STRING_LENGTH = 100
+
+class PickledObject(unicode):
+    pass
+
+def dbsafe_encode(value, compress_object=True):
+    if not compress_object:
+        value = b64encode(dumps(deepcopy(value)))
+    else:
+        value = b64encode(compress(dumps(deepcopy(value))))
+    return PickledObject(value)
+
+def dbsafe_decode(value, compress_object=True):
+    if not compress_object:
+        value = loads(b64decode(value))
+    else:
+        value = loads(decompress(b64decode(value)))
+    return value
+
+class PickledObjectField(models.Field):
+    __metaclass__ = models.SubfieldBase
+
+    marker_re = re.compile(r'^T\[(?P<type>\w+)\](?P<value>.*)$', re.DOTALL)
+    markable_types = dict((t.__name__, t) for t in (str, int, unicode))
+
+    def __init__(self, *args, **kwargs):
+        self.compress = kwargs.pop('compress', True)
+        self.protocol = kwargs.pop('protocol', 2)
+        kwargs.setdefault('null', True)
+        kwargs.setdefault('editable', False)
+        super(PickledObjectField, self).__init__(*args, **kwargs)
+
+    def generate_type_marked_value(self, value):
+        return PickledObject(u"T[%s]%s" % (type(value).__name__, value))
+
+    def read_marked_value(self, value):
+        m = self.marker_re.match(value)
+
+        if m:
+            marker = m.group('type')
+            value = m.group('value')
+            if marker in self.markable_types:
+                value = self.markable_types[marker](value)
+
+        return value
+
+    def get_default(self):
+        if self.has_default():
+            if callable(self.default):
+                return self.default()
+            return self.default
+
+        return super(PickledObjectField, self).get_default()
+
+    def to_python(self, value):
+        if value is not None:
+            try:
+                if value.startswith("T["):
+                    value = self.read_marked_value(value)
+                else:
+                    value = dbsafe_decode(value, self.compress)
+            except:
+                if isinstance(value, PickledObject):
+                    raise
+        return value
+
+    def get_db_prep_value(self, value):
+        if value is not None and not isinstance(value, PickledObject):
+            if type(value).__name__ in self.markable_types and not (isinstance(value, basestring) and len(value
+                                                                                                          ) > MAX_MARKABLE_STRING_LENGTH):
+                value = unicode(self.generate_type_marked_value(value))
+            else:
+                value = unicode(dbsafe_encode(value, self.compress))
+        return value
+
+    def value_to_string(self, obj):
+        value = self._get_val_from_obj(obj)
+        return self.get_db_prep_value(value)
+
+    def get_internal_type(self):
+        return 'TextField'
+
+    def get_db_prep_lookup(self, lookup_type, value):
+        if lookup_type not in ['exact', 'in', 'isnull']:
+            raise TypeError('Lookup type %s is not supported.' % lookup_type)
+        return super(PickledObjectField, self).get_db_prep_lookup(lookup_type, value)
+
+
+class KeyValue(BaseModel):
+    key = models.CharField(max_length=255, unique=True)
+    value = PickledObjectField()
+
+    class Meta:
+        app_label = 'forum'
+
+    def cache_key(self):
+        return self._generate_cache_key(self.key)
+
+    @classmethod
+    def infer_cache_key(cls, querydict):
+        try:
+            key = [v for (k, v) in querydict.items() if k in ('key', 'key__exact')][0]
+
+            return cls._generate_cache_key(key)
+        except:
+            return None
+
diff --git a/forum/modules/template_loader.py/forum/modules/__init__.py b/forum/modules/template_loader.py/forum/modules/__init__.py
new file mode 100644 (file)
index 0000000..d4dd67c
--- /dev/null
@@ -0,0 +1,94 @@
+import os
+import types
+import re
+import logging
+
+from django.template import Template, TemplateDoesNotExist
+from django.conf import settings
+
+MODULES_PACKAGE = 'forum_modules'
+
+MODULES_FOLDER = os.path.join(settings.SITE_SRC_ROOT, MODULES_PACKAGE)
+
+DISABLED_MODULES = getattr(settings, 'DISABLED_MODULES', [])
+
+MODULE_LIST = filter(lambda m: getattr(m, 'CAN_USE', True), [
+        __import__('forum_modules.%s' % f, globals(), locals(), ['forum_modules'])
+        for f in os.listdir(MODULES_FOLDER)
+        if os.path.isdir(os.path.join(MODULES_FOLDER, f)) and
+           os.path.exists(os.path.join(MODULES_FOLDER, "%s/__init__.py" % f)) and
+           not f in DISABLED_MODULES
+])
+
+def get_modules_script(script_name):
+    all = []
+
+    for m in MODULE_LIST:
+        try:
+            all.append(__import__('%s.%s' % (m.__name__, script_name), globals(), locals(), [m.__name__]))
+        except ImportError, e:
+            #print repr(type(e)) + m.__name__ + ":" + str(e)
+            pass
+        except:
+            import traceback
+            msg = "Error importing %s from module %s: \n %s" % (
+                script_name, m.__name__, traceback.format_exc()
+            )
+            logging.error(msg)
+
+    return all
+
+def get_modules_script_implementations(script_name, impl_class):
+    scripts = get_modules_script(script_name)
+    all_impls = {}
+
+    for script in scripts:
+        all_impls.update(dict([
+            (n, i) for (n, i) in [(n, getattr(script, n)) for n in dir(script)]
+            if isinstance(i, impl_class)
+        ]))
+
+    return all_impls
+
+def get_modules_script_classes(script_name, base_class):
+    scripts = get_modules_script(script_name)
+    all_classes = {}
+
+    for script in scripts:
+        all_classes.update(dict([
+            (n, c) for (n, c) in [(n, getattr(script, n)) for n in dir(script)]
+            if isinstance(c, (type, types.ClassType)) and issubclass(c, base_class)
+        ]))
+
+    return all_classes
+
+def get_all_handlers(name):
+     handler_files = get_modules_script('handlers')
+
+     return [
+        h for h in [
+            getattr(f, name) for f in handler_files
+            if hasattr(f, name)
+        ]
+
+        if callable(h)
+     ]
+
+def call_all_handlers(name, *args, **kwargs):
+    all = get_all_handlers(name)
+
+    ret = []
+
+    for handler in all:
+        ret.append(handler(*args, **kwargs))
+
+    return ret
+
+def get_handler(name, default):
+    all = get_all_handlers(name)
+    return len(all) and all[0] or default
+
+from template_loader import ModulesTemplateLoader
+module_templates_loader = ModulesTemplateLoader()
+
+from decorators import decorate, ReturnImediatelyException
diff --git a/forum/modules/template_loader.py/forum/modules/decorators.py b/forum/modules/template_loader.py/forum/modules/decorators.py
new file mode 100644 (file)
index 0000000..3c53412
--- /dev/null
@@ -0,0 +1,156 @@
+import inspect\r
+\r
+class DecoratableObject(object):\r
+    MODE_OVERRIDE = 0\r
+    MODE_PARAMS = 1\r
+    MODE_RESULT = 2\r
+\r
+    def __init__(self, fn, is_method=False):\r
+        self._callable = fn\r
+        self.is_method = is_method\r
+\r
+        self._params_decoration = None\r
+        self._result_decoration = None\r
+\r
+    def _decorate(self, fn, mode, **kwargs):\r
+        if mode == self.MODE_OVERRIDE:\r
+            self._decorate_full(fn, **kwargs)\r
+        elif mode == self.MODE_PARAMS:\r
+            self._decorate_params(fn)\r
+        elif mode == self.MODE_RESULT:\r
+            self._decorate_result(fn, **kwargs)\r
+\r
+    def _decorate_full(self, fn, needs_origin=True):\r
+        origin = self._callable\r
+\r
+        if needs_origin:\r
+            if self.is_method:\r
+                self._callable = lambda inst, *args, **kwargs: fn(inst, origin, *args, **kwargs)\r
+            else:\r
+                self._callable = lambda *args, **kwargs: fn(origin, *args, **kwargs)\r
+        else:\r
+            self._callable = fn\r
+\r
+    def _decorate_params(self, fn):\r
+        if not self._params_decoration:\r
+            self._params_decoration = []\r
+\r
+        self._params_decoration.append(fn)\r
+\r
+    def _decorate_result(self, fn, needs_params=False):\r
+        if not self._result_decoration:\r
+            self._result_decoration = []\r
+\r
+        fn._needs_params = needs_params\r
+        self._result_decoration.append(fn)\r
+\r
+    def __call__(self, *args, **kwargs):\r
+        if self._params_decoration:\r
+            for dec in self._params_decoration:\r
+                try:\r
+                    args, kwargs = dec(*args, **kwargs)\r
+                except ReturnImediatelyException, e:\r
+                    return e.ret\r
+\r
+        res = self._callable(*args, **kwargs)\r
+\r
+        if self._result_decoration:\r
+            for dec in self._result_decoration:\r
+                if dec._needs_params:\r
+                    res = dec(res, *args, **kwargs)\r
+                else:\r
+                    res = dec(res)\r
+\r
+        return res\r
+\r
+class ReturnImediatelyException(Exception):\r
+    def __init__(self, ret):\r
+        super(Exception, self).__init__()\r
+        self.ret = ret\r
+\r
+def _check_decoratable(origin, install=True):\r
+    if not isinstance(origin, DecoratableObject):\r
+        if inspect.ismethod(origin) and not hasattr(origin, '_decoratable_obj'):\r
+            decoratable = DecoratableObject(origin)\r
+\r
+            def decoratable_method(self, *args, **kwargs):\r
+                return decoratable(self, *args, **kwargs)\r
+\r
+            decoratable_method._decoratable_obj = decoratable\r
+\r
+            def decoratable_decorate(fn, mode, **kwargs):\r
+                decoratable._decorate(fn, mode, **kwargs)\r
+\r
+            decoratable_method._decorate = decoratable_decorate\r
+\r
+            if install:\r
+                setattr(origin.im_class, origin.__name__, decoratable_method)\r
+\r
+            return decoratable_method\r
+                \r
+        elif inspect.isfunction(origin):\r
+            decoratable = DecoratableObject(origin)\r
+\r
+            if install:\r
+                setattr(inspect.getmodule(origin), origin.__name__, decoratable)\r
+\r
+            return decoratable\r
+\r
+    return origin\r
+\r
+\r
+def decorate(origin, needs_origin=True):\r
+    origin = _check_decoratable(origin)\r
+\r
+    def decorator(fn):\r
+        origin._decorate(fn, DecoratableObject.MODE_OVERRIDE, needs_origin=needs_origin)\r
+        \r
+    return decorator\r
+\r
+\r
+def _decorate_params(origin):\r
+    origin = _check_decoratable(origin)\r
+\r
+    def decorator(fn):\r
+        origin._decorate(fn, DecoratableObject.MODE_PARAMS)\r
+\r
+    return decorator\r
+\r
+decorate.params = _decorate_params\r
+\r
+def _decorate_result(origin, needs_params=False):\r
+    origin = _check_decoratable(origin)\r
+\r
+    def decorator(fn):\r
+        origin._decorate(fn, DecoratableObject.MODE_RESULT, needs_params=needs_params)\r
+\r
+    return decorator\r
+\r
+decorate.result = _decorate_result\r
+\r
+def _decorate_with(fn):\r
+    def decorator(origin):\r
+        origin = _check_decoratable(origin)\r
+        origin._decorate(fn, DecoratableObject.MODE_OVERRIDE, needs_origin=True)\r
+        return origin\r
+    return decorator\r
+\r
+decorate.withfn = _decorate_with\r
+\r
+def _decorate_result_with(fn, needs_params=False):\r
+    def decorator(origin):\r
+        origin = _check_decoratable(origin)\r
+        origin._decorate(fn, DecoratableObject.MODE_RESULT, needs_params=needs_params)\r
+        return origin\r
+    return decorator\r
+\r
+decorate.result.withfn = _decorate_result_with\r
+\r
+def _decorate_params_with(fn):\r
+    def decorator(origin):\r
+        origin = _check_decoratable(origin)\r
+        origin._decorate(fn, DecoratableObject.MODE_PARAMS)\r
+        return origin\r
+    return decorator\r
+\r
+decorate.params.withfn = _decorate_params_with
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/modules/template_loader.py b/forum/modules/template_loader.py/forum/modules/template_loader.py
new file mode 100644 (file)
index 0000000..ecf6400
--- /dev/null
@@ -0,0 +1,43 @@
+import os, re
+
+from forum.skins import load_template_source as skins_template_loader, Template, BaseTemplateLoader
+from forum.modules import MODULES_FOLDER, MODULE_LIST
+
+MODULES_TEMPLATE_PREFIX = 'modules/'
+NO_OVERRIDE_TEMPLATE_PREFIX = 'no_override/'
+MODULES_TEMPLATE_FOLDER = 'templates'
+MODULES_TEMPLATE_OVERRIDES_FOLDER = 'template_overrides'
+
+TEMPLATE_OVERRIDE_LOOKUP_PATHS = [f for f in [
+        os.path.join(os.path.dirname(m.__file__), MODULES_TEMPLATE_OVERRIDES_FOLDER) for m in MODULE_LIST
+    ] if os.path.exists(f)
+]
+
+class ModulesTemplateLoader(BaseTemplateLoader):
+
+    modules_re = re.compile('^%s(\w+)\/(.*)$' % MODULES_TEMPLATE_PREFIX)
+
+    def load_template_source(self, name, dirs=None):
+        template = None
+
+        if name.startswith(MODULES_TEMPLATE_PREFIX):
+            match = self.modules_re.search(name)
+            file_name = os.path.join(MODULES_FOLDER, match.group(1), MODULES_TEMPLATE_FOLDER, match.group(2))
+
+            if os.path.exists(file_name):
+                template = Template(file_name)
+
+        elif name.startswith(NO_OVERRIDE_TEMPLATE_PREFIX):
+            return skins_template_loader.load_template_source(name[len(NO_OVERRIDE_TEMPLATE_PREFIX):], dirs)
+
+        else:
+            for override_path in TEMPLATE_OVERRIDE_LOOKUP_PATHS:
+                file_name = os.path.join(override_path, name)
+
+                if os.path.exists(file_name):
+                    template = Template(file_name)
+                    break
+
+
+        return template
+
diff --git a/forum/modules/template_loader.py/forum/modules/ui.py b/forum/modules/template_loader.py/forum/modules/ui.py
new file mode 100644 (file)
index 0000000..48c0246
--- /dev/null
@@ -0,0 +1,51 @@
+
+
+class Registry(list):
+    def add(self, item):
+        for i, r in enumerate(self):
+            if r.weight > item.weight:
+                self.insert(i, item)
+                return
+
+        self.append(item)
+
+
+HEAD_CONTENT = 'HEAD_CONTENT'
+HEADER_LINKS = 'HEADER_LINKS'
+PAGE_TOP_TABS = 'PAGE_TOP_TABS'
+FOOTER_LINKS = 'FOOTER_LINKS'
+PROFILE_TABS = 'PROFILE_TABS'
+
+USER_MENU = 'USER_MENU'
+
+
+__CONTAINER = {
+    HEAD_CONTENT: Registry(),
+    HEADER_LINKS: Registry(),
+    PAGE_TOP_TABS: Registry(),
+    FOOTER_LINKS: Registry(),
+    PROFILE_TABS: Registry(),
+
+    USER_MENU: Registry(),
+}
+
+
+def register(registry, *ui_objects):
+    if not registry in __CONTAINER:
+        raise('unknown registry')
+
+    for ui_object in ui_objects:
+        __CONTAINER[registry].add(ui_object)
+
+def get_registry_by_name(name):
+    name = name.upper()
+
+    if not name in __CONTAINER:
+        raise('unknown registry')
+
+    return __CONTAINER[name]
+
+
+
+from ui_objects import *
+
diff --git a/forum/modules/template_loader.py/forum/modules/ui_objects.py b/forum/modules/template_loader.py/forum/modules/ui_objects.py
new file mode 100644 (file)
index 0000000..e42c940
--- /dev/null
@@ -0,0 +1,210 @@
+from django.core.urlresolvers import reverse
+from django.template.defaultfilters import slugify
+from django import template
+from forum.utils import html
+from forum.models.user import AnonymousUser
+from ui import Registry
+from copy import copy
+
+class Visibility(object):
+    def __init__(self, level='public'):
+        if level not in ['public', 'authenticated', 'staff', 'superuser', 'owner']:
+            try:
+                int(level)
+                self.by_reputation = True
+            except:
+                raise "Invalid visibility level for ui object: %s" % level
+        else:
+            self.by_reputation = False
+
+        self.level = level
+        self.negated = False
+
+    def show_to(self, user):
+        if self.by_reputation:
+            res = user.is_authenticated() and (user.reputation >= int(self.level) or user.is_staff or user.is_superuser)
+        else:
+            res = self.level == 'public' or (user.is_authenticated() and (
+                self.level == 'authenticated' or (
+                self.level == 'superuser' and user.is_superuser) or (
+                self.level == 'staff' and (user.is_staff or user.is_superuser)) or (
+                self.level == 'owner' and user.is_siteowner)))
+
+        if self.negated:
+            return not res
+        else:
+            return res
+
+    def __invert__(self):
+        inverted = copy(self)
+        inverted.negated = True
+        
+
+Visibility.PUBLIC = Visibility('public')
+Visibility.AUTHENTICATED = Visibility('authenticated')
+Visibility.STAFF = Visibility('staff')
+Visibility.SUPERUSER = Visibility('superuser')
+Visibility.OWNER = Visibility('owner')
+Visibility.REPUTED = lambda r: Visibility(r)
+
+
+class Url(object):
+    def __init__(self, url_pattern):
+        self.url_pattern = url_pattern
+
+    def __call__(self, u, c):
+        return reverse(self.url_pattern)
+
+
+class ObjectBase(object):
+    class Argument(object):
+        def __init__(self, argument):
+            self.argument = argument
+
+        def __call__(self, context):
+            if callable(self.argument):
+                user = context.get('request', None) and context['request'].user or AnonymousUser()
+                return self.argument(user, context)
+            else:
+                return self.argument
+
+    def __init__(self, visibility=None, weight=500):
+        self.visibility = visibility
+        self.weight = weight
+
+    def _visible_to(self, user):
+        return (not self.visibility) or (self.visibility and self.visibility.show_to(user))
+
+    def can_render(self, context):
+        try:
+            return self._visible_to(context['request'].user)
+        except KeyError:
+            try:
+                return self._visible_to(context['viewer'])
+            except KeyError:
+                return self._visible_to(AnonymousUser())
+
+    def render(self, context):
+        return ''
+
+class LoopBase(ObjectBase):
+    def update_context(self, context):
+        pass
+
+
+
+class Link(ObjectBase):
+    def __init__(self, text, url, attrs=None, pre_code='', post_code='', visibility=None, weight=500):
+        super(Link, self).__init__(visibility, weight)
+        self.text = self.Argument(text)
+        self.url = self.Argument(url)
+        self.attrs = self.Argument(attrs or {})
+        self.pre_code = self.Argument(pre_code)
+        self.post_code = self.Argument(post_code)
+
+    def render(self, context):
+        return "%s %s %s" % (self.pre_code(context),
+            html.hyperlink(self.url(context), self.text(context), **self.attrs(context)),
+            self.post_code(context))
+
+class Include(ObjectBase):
+    def __init__(self, tpl, visibility=None, weight=500):
+        super(Include, self).__init__(visibility, weight)
+        self.template = template.loader.get_template(tpl)
+
+    def render(self, context):
+        if not isinstance(context, template.Context):
+            context = template.Context(context)
+        return self.template.render(context)
+        
+
+class LoopContext(LoopBase):
+    def __init__(self, loop_context, visibility=None, weight=500):
+        super(LoopContext, self).__init__(visibility, weight)
+        self.loop_context = self.Argument(loop_context)
+
+    def update_context(self, context):
+        context.update(self.loop_context(context))
+
+
+class PageTab(LoopBase):
+    def __init__(self, tab_name, tab_title, url_getter, weight):
+        super(PageTab, self).__init__(weight=weight)
+        self.tab_name = tab_name
+        self.tab_title = tab_title
+        self.url_getter = url_getter
+
+    def update_context(self, context):
+        context.update(dict(
+            tab_name=self.tab_name,
+            tab_title=self.tab_title,
+            tab_url=self.url_getter()
+        ))
+
+
+class ProfileTab(LoopBase):
+    def __init__(self, name, title, description, url_getter, private=False, render_to=None, weight=500):
+        super(ProfileTab, self).__init__(weight=weight)
+        self.name = name
+        self.title = title
+        self.description = description
+        self.url_getter = url_getter
+        self.private = private
+        self.render_to = render_to
+
+    def can_render(self, context):
+        return (not self.render_to or (self.render_to(context['view_user']))) and (
+            not self.private or (
+            context['view_user'] == context['request'].user or context['request'].user.is_superuser))
+
+    def update_context(self, context):        
+        context.update(dict(
+            tab_name=self.name,
+            tab_title=self.title,
+            tab_description = self.description,
+            tab_url=self.url_getter(context['view_user'])
+        ))
+
+
+class AjaxMenuItem(ObjectBase):
+    def __init__(self, label, url, a_attrs=None, span_label='', span_attrs=None, visibility=None, weight=500):
+        super(AjaxMenuItem, self).__init__(visibility, weight)
+        self.label = self.Argument(label)
+        self.url = self.Argument(url)
+        self.a_attrs = self.Argument(a_attrs or {})
+        self.span_label = self.Argument(span_label)
+        self.span_attrs = self.Argument(span_attrs or {})
+
+    def render(self, context):
+        return html.buildtag('li',
+            html.buildtag('span', self.span_label(context), **self.span_attrs(context)) + \
+            html.hyperlink(self.url(context), self.label(context), **self.a_attrs(context)),
+            **{'class': 'item'})
+
+class AjaxMenuGroup(ObjectBase, Registry):
+    def __init__(self, label, items, visibility=None, weight=500):
+        super(AjaxMenuGroup, self).__init__(visibility, weight)
+        self.label = label
+
+        for item in items:
+            self.add(item)
+
+    def can_render(self, context):
+        if super(AjaxMenuGroup, self).can_render(context):
+            for item in self:
+                if item.can_render(context): return True
+
+        return False
+
+    def render(self, context):
+        return html.buildtag('li', self.label, **{'class': 'separator'}) + "".join([
+            item.render(context) for item in self if item.can_render(context)
+        ])
+
+class UserMenuItem(AjaxMenuItem):
+    def __init__(self, render_to=None, *args, **kwargs):
+        super(UserMenuItem, self).__init__(*args, **kwargs)
+        self.render_to = render_to
+
+    def can_render(self, context):
+        return (not self.render_to or (self.render_to(context['user']))) and super(UserMenuItem, self)._visible_to(context['viewer'])
diff --git a/forum/modules/template_loader.py/forum/registry.py b/forum/modules/template_loader.py/forum/registry.py
new file mode 100644 (file)
index 0000000..ff5a115
--- /dev/null
@@ -0,0 +1,109 @@
+from forum.modules import ui
+from django.utils.translation import ugettext as _
+from django.core.urlresolvers import reverse
+from django.template.defaultfilters import slugify
+from forum.templatetags.extra_tags import get_score_badge
+from forum.utils.html import cleanup_urls
+from forum import settings
+
+
+ui.register(ui.HEADER_LINKS,
+            ui.Link(_('faq'), ui.Url('faq'), weight=400),
+            ui.Link(_('about'), ui.Url('about'), weight=300),
+
+            ui.Link(
+                    text=lambda u, c: u.is_authenticated() and _('logout') or _('login'),
+                    url=lambda u, c: u.is_authenticated() and reverse('logout') or reverse('auth_signin'),
+                    weight=200),
+
+            ui.Link(
+                    visibility=ui.Visibility.AUTHENTICATED,
+                    text=lambda u, c: u.username,
+                    url=lambda u, c: u.get_profile_url(),
+                    post_code=lambda u, c: get_score_badge(u),
+                    weight=100),
+
+            ui.Link(
+                    visibility=ui.Visibility.SUPERUSER,
+                    text=_('administration'),
+                    url=lambda u, c: reverse('admin_index'),
+                    weight=0)
+
+)
+
+class SupportLink(ui.Link):
+    def can_render(self, context):
+        return bool(settings.SUPPORT_URL)
+
+
+ui.register(ui.FOOTER_LINKS,
+            ui.Link(
+                    text=_('contact'),
+                    url=lambda u, c: settings.CONTACT_URL and settings.CONTACT_URL or "%s?next=%s" % (reverse('feedback'), cleanup_urls( c['request'].path)),
+                    weight=400),
+            SupportLink(_('support'), settings.SUPPORT_URL, attrs={'target': '_blank'}, weight=300),
+            ui.Link(_('privacy'), ui.Url('privacy'), weight=200),
+            ui.Link(_('faq'), ui.Url('faq'), weight=100),
+            ui.Link(_('about'), ui.Url('about'), weight=0),
+)
+
+class ModerationMenuGroup(ui.AjaxMenuGroup):
+    def can_render(self, context):
+        return context['user'] != context['viewer'] and super(ModerationMenuGroup, self).can_render(context)
+
+class SuperUserSwitchMenuItem(ui.UserMenuItem):
+    def can_render(self, context):
+        return context['viewer'].is_siteowner or not context['user'].is_superuser
+
+ui.register(ui.USER_MENU,
+            ui.UserMenuItem(
+                label=_("edit profile"),
+                url=lambda u, c: reverse('edit_user', kwargs={'id': c['user'].id}),
+                span_attrs={'class': 'user-edit'},
+                weight=0
+            ),
+            ui.UserMenuItem(
+                label=_("authentication settings"),
+                url=lambda u, c: reverse('user_authsettings', kwargs={'id': c['user'].id}),
+                span_attrs={'class': 'user-auth'},
+                weight=100
+            ),
+            ui.UserMenuItem(
+                label=_("email notification settings"),
+                url=lambda u, c: reverse('user_subscriptions', kwargs={'id': c['user'].id, 'slug': slugify(c['user'].username)}),
+                span_attrs={'class': 'user-subscriptions'},
+                weight=200
+            ),
+            ui.UserMenuItem(
+                label=_("other preferences"),
+                url=lambda u, c: reverse('user_preferences', kwargs={'id': c['user'].id, 'slug': slugify(c['user'].username)}),
+                weight=200
+            ),
+            ModerationMenuGroup(_("Moderation tools"), items=(
+                ui.UserMenuItem(
+                    label=lambda u, c: c['user'].is_suspended() and _("withdraw suspension") or _("suspend this user"),
+                    url=lambda u, c: reverse('user_suspend', kwargs={'id': c['user'].id}),
+                    a_attrs=lambda u, c: {'class': c['user'].is_suspended() and 'ajax-command confirm' or 'ajax-command withprompt'},
+                    render_to=lambda u: not u.is_superuser,
+                ),
+                ui.UserMenuItem(
+                    label=lambda u, c: _("give/take karma"),
+                    url=lambda u, c: reverse('user_award_points', kwargs={'id': c['user'].id}),
+                    a_attrs=lambda u, c: {'id': 'award-rep-points', 'class': 'ajax-command withprompt'},
+                    span_attrs={'class': 'user-award_rep'},
+                    render_to=lambda u: not u.is_suspended(),
+                ),
+                ui.UserMenuItem(
+                    label=lambda u, c: c['user'].is_staff and _("remove moderator status") or _("grant moderator status"),
+                    url=lambda u, c: reverse('user_powers', kwargs={'id': c['user'].id, 'action':c['user'].is_staff and 'remove' or 'grant', 'status': 'staff'}),
+                    a_attrs=lambda u, c: {'class': 'ajax-command confirm'},
+                    span_attrs={'class': 'user-moderator'},
+                ),
+                SuperUserSwitchMenuItem(
+                    label=lambda u, c: c['user'].is_superuser and _("remove super user status") or _("grant super user status"),
+                    url=lambda u, c: reverse('user_powers', kwargs={'id': c['user'].id, 'action':c['user'].is_superuser and 'remove' or 'grant', 'status': 'super'}),
+                    a_attrs=lambda u, c: {'class': 'ajax-command confirm'},
+                    span_attrs={'class': 'user-superuser'},
+                ),
+            ), visibility=ui.Visibility.SUPERUSER, weight=500)
+)
diff --git a/forum/modules/template_loader.py/forum/settings/__init__.py b/forum/modules/template_loader.py/forum/settings/__init__.py
new file mode 100644 (file)
index 0000000..e10fc76
--- /dev/null
@@ -0,0 +1,48 @@
+import os.path
+from base import Setting, SettingSet
+
+from django.forms.widgets import Textarea
+from django.utils.translation import ugettext_lazy as _
+from django.conf import settings as djsettings
+from django.utils.version import get_svn_revision
+
+OSQA_VERSION = "Development Build"
+SVN_REVISION = get_svn_revision(djsettings.SITE_SRC_ROOT)
+
+MAINTAINANCE_MODE = Setting('MAINTAINANCE_MODE', None)
+
+SETTINGS_PACK = Setting('SETTINGS_PACK', "default")
+DJSTYLE_ADMIN_INTERFACE = Setting('DJSTYLE_ADMIN_INTERFACE', True)
+NODE_MAN_FILTERS = Setting('NODE_MAN_FILTERS', [])
+
+APP_URL = djsettings.APP_URL
+APP_BASE_URL = djsettings.APP_BASE_URL
+FORCE_SCRIPT_NAME = djsettings.FORCE_SCRIPT_NAME
+OSQA_SKIN = djsettings.OSQA_DEFAULT_SKIN
+LANGUAGE_CODE = djsettings.LANGUAGE_CODE
+ADMIN_MEDIA_PREFIX = djsettings.ADMIN_MEDIA_PREFIX
+ONLINE_USERS = Setting('ONLINE_USERS', {})
+
+
+from basic import *
+from sidebar import *
+from email import *
+from extkeys import *
+from minrep import *
+from repgain import *
+from voting import *
+from upload import *
+from about import *
+from faq import *
+from form import *
+from view import *
+from moderation import *
+from users import *
+from static import *
+from urls import *
+from accept import *
+
+BADGES_SET = SettingSet('badges', _('Badges config'), _("Configure badges on your OSQA site."), 500)
+
+#__all__ = locals().keys()
+
diff --git a/forum/modules/template_loader.py/forum/settings/about.py b/forum/modules/template_loader.py/forum/settings/about.py
new file mode 100644 (file)
index 0000000..b4f1a64
--- /dev/null
@@ -0,0 +1,28 @@
+from base import Setting, SettingSet
+from django.forms.widgets import Textarea
+
+PAGES_SET = SettingSet('about', 'About page', "Define the text in the about page. You can use markdown and some basic html tags.", 2000, True)
+
+ABOUT_PAGE_TEXT = Setting('ABOUT_PAGE_TEXT',
+u"""
+**Please customize this text in the administration area**
+
+Here you can **ask** and **answer** questions, **comment**
+and **vote** for the questions of others and their answers. Both questions and answers
+**can be revised** and improved. Questions can be **tagged** with
+the relevant keywords to simplify future access and organize the accumulated material.
+
+This <span class="orange">Q&amp;A</span> site is moderated by its members, hopefully - including yourself!
+Moderation rights are gradually assigned to the site users based on the accumulated "**karma**"
+points. These points are added to the users account when others vote for his/her questions or answers.
+These points (very) roughly reflect the level of trust of the community.
+
+No points are necessary to ask or answer the questions - so please - join us!
+
+If you would like to find out more about this site - please see the **frequently asked questions** page.
+""", PAGES_SET, dict(
+label = "About page text",
+help_text = """
+The about page.
+""",
+widget=Textarea(attrs={'rows': '20'})))
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/settings/accept.py b/forum/modules/template_loader.py/forum/settings/accept.py
new file mode 100644 (file)
index 0000000..aa29e09
--- /dev/null
@@ -0,0 +1,25 @@
+from base import Setting, SettingSet
+from django.forms.widgets import RadioSelect
+from django.utils.translation import ugettext_lazy as _
+
+ACCEPT_SET = SettingSet('accept', _('Accepting answers'), _("Settings to tweak the behaviour of accepting answers."), 500)
+
+DISABLE_ACCEPTING_FEATURE = Setting('DISABLE_ACCEPTING_FEATURE', False, ACCEPT_SET, dict(
+label = _("Disallow answers to be accepted"),
+help_text = _("Disable accepting answers feature. If you re-enable it in the future, currently accepted answers will still be marked as accepted."),
+required=False))
+
+MAXIMUM_ACCEPTED_ANSWERS = Setting('MAXIMUM_ACCEPTED_ANSWERS', 1, ACCEPT_SET, dict(
+label = _("Maximum accepted answers per question"),
+help_text = _("How many accepted answers are allowed per question. Use 0 for no limit.")))
+
+MAXIMUM_ACCEPTED_PER_USER = Setting('MAXIMUM_ACCEPTED_PER_USER', 1, ACCEPT_SET, dict(
+label = _("Maximum accepted answers per user/question"),
+help_text = _("If more than one accpeted answer is allowed, how many can be accepted per single user per question.")))
+
+USERS_CAN_ACCEPT_OWN = Setting('USERS_CAN_ACCEPT_OWN', False, ACCEPT_SET, dict(
+label = _("Users an accept own answer"),
+help_text = _("Are normal users allowed to accept their own answers.."),
+required=False))
+
+
diff --git a/forum/modules/template_loader.py/forum/settings/base.py b/forum/modules/template_loader.py/forum/settings/base.py
new file mode 100644 (file)
index 0000000..7436f46
--- /dev/null
@@ -0,0 +1,128 @@
+import django.dispatch
+from django.utils.encoding import force_unicode
+from datetime import datetime, timedelta
+import logging
+
+TMP_MINICACHE_SECONDS = 5
+
+class SettingSet(list):
+    def __init__(self, name, title, description, weight=1000, markdown=False, can_preview=False):
+        self.name = name
+        self.title = title
+        self.description = description
+        self.weight = weight
+        self.markdown = markdown
+        self.can_preview = can_preview
+
+
+class BaseSetting(object):
+    @classmethod
+    def add_to_class(cls, name):
+        def wrapper(self, *args, **kwargs):
+            return self.value.__getattribute__(name)(*args, **kwargs)
+
+        setattr(cls, name, wrapper)
+
+    def __init__(self, name, default, set=None, field_context=None):
+        self.name = name
+        self.default = default
+        self.field_context = field_context or {}
+
+        self._temp = None
+
+        if set is not None:
+            self.set = set
+            
+            if not set.name in Setting.sets:
+                Setting.sets[set.name] = set
+
+            Setting.sets[set.name].append(self)
+
+    def __str__(self):
+        return str(self.value)
+
+    def __unicode__(self):
+        return unicode(self.value)
+
+    @property
+    def value(self):
+        if self._temp:
+            v, exp = self._temp
+            if exp + timedelta(seconds=TMP_MINICACHE_SECONDS) > datetime.now():
+                return v
+
+        from forum.models import KeyValue
+
+        try:
+            kv = KeyValue.objects.get(key=self.name)
+            v = kv.value
+            self._temp = (v, datetime.now() + timedelta(seconds=TMP_MINICACHE_SECONDS))
+            return v
+        except KeyValue.DoesNotExist:
+            self._temp = (self.default, datetime.now() + timedelta(seconds=TMP_MINICACHE_SECONDS))
+            self.save(self.default)
+        except Exception, e:
+            logging.error("Error retrieving setting from database (%s): %s" % (self.name, str(e)))
+            
+        return self.default
+
+    def set_value(self, new_value):
+        new_value = self._parse(new_value)
+        self._temp = None
+        self.save(new_value)
+
+    def save(self, value):
+        from forum.models import KeyValue
+
+        try:
+            kv = KeyValue.objects.get(key=self.name)
+        except KeyValue.DoesNotExist:
+            kv = KeyValue(key=self.name)
+        except Exception, e:
+            logging.error("Error savin setting to database (%s): %s" % (self.name, str(e)))
+            return
+
+        kv.value = value
+        kv.save()
+
+    def to_default(self):
+        self.set_value(self.default)
+
+    def _parse(self, value):
+        if not isinstance(value, self.base_type):
+            try:
+                return self.base_type(value)
+            except:
+                pass
+        return value
+
+class AnyTypeSetting(BaseSetting):
+     def _parse(self, value):
+        return value
+
+
+class Setting(object):
+    emulators = {}
+    sets = {}
+
+    def __new__(cls, name, default, set=None, field_context=None):
+        if default is None:
+            return AnyTypeSetting(name, default, set, field_context)
+            
+        deftype = type(default)
+
+        if deftype in Setting.emulators:
+            emul = Setting.emulators[deftype]
+        else:
+            emul = type(deftype.__name__ + cls.__name__, (BaseSetting,), {'base_type': deftype})
+
+            fns = [n for n, f in [(p, getattr(deftype, p)) for p in dir(deftype) if not p in dir(cls)] if callable(f)]
+
+            for n in fns:
+               emul.add_to_class(n)
+
+            Setting.emulators[deftype] = emul
+
+        return emul(name, default, set, field_context)
+
+
diff --git a/forum/modules/template_loader.py/forum/settings/basic.py b/forum/modules/template_loader.py/forum/settings/basic.py
new file mode 100644 (file)
index 0000000..a4efd6f
--- /dev/null
@@ -0,0 +1,52 @@
+import os.path\r
+\r
+from base import Setting, SettingSet\r
+from forms import ImageFormWidget\r
+\r
+from django.utils.translation import ugettext_lazy as _\r
+from django.forms.widgets import Textarea\r
+\r
+BASIC_SET = SettingSet('basic', _('Basic settings'), _("The basic settings for your application"), 1)\r
+\r
+APP_LOGO = Setting('APP_LOGO', '/upfiles/logo.png', BASIC_SET, dict(\r
+label = _("Application logo"),\r
+help_text = _("Your site main logo."),\r
+widget=ImageFormWidget))\r
+\r
+APP_FAVICON = Setting('APP_FAVICON', '/m/default/media/images/favicon.ico', BASIC_SET, dict(\r
+label = _("Favicon"),\r
+help_text = _("Your site favicon."),\r
+widget=ImageFormWidget))\r
+\r
+APP_TITLE = Setting('APP_TITLE', u'OSQA: Open Source Q&A Forum', BASIC_SET, dict(\r
+label = _("Application title"),\r
+help_text = _("The title of your application that will show in the browsers title bar")))\r
+\r
+APP_SHORT_NAME = Setting(u'APP_SHORT_NAME', 'OSQA', BASIC_SET, dict(\r
+label = _("Application short name"),\r
+help_text = "The short name for your application that will show up in many places."))\r
+\r
+APP_KEYWORDS = Setting('APP_KEYWORDS', u'OSQA,CNPROG,forum,community', BASIC_SET, dict(\r
+label = _("Application keywords"),\r
+help_text = _("The meta keywords that will be available through the HTML meta tags.")))\r
+\r
+APP_DESCRIPTION = Setting('APP_DESCRIPTION', u'Ask and answer questions.', BASIC_SET, dict(\r
+label = _("Application description"),\r
+help_text = _("The description of your application"),\r
+widget=Textarea))\r
+\r
+APP_COPYRIGHT = Setting('APP_COPYRIGHT', u'Copyright OSQA, 2010. Some rights reserved under creative commons license.', BASIC_SET, dict(\r
+label = _("Copyright notice"),\r
+help_text = _("The copyright notice visible at the footer of your page.")))\r
+\r
+SUPPORT_URL = Setting('SUPPORT_URL', '', BASIC_SET, dict(\r
+label = _("Support URL"),\r
+help_text = _("The URL provided for users to get support. It can be http: or mailto: or whatever your preferred support scheme is."),\r
+required=False))\r
+\r
+CONTACT_URL = Setting('CONTACT_URL', '', BASIC_SET, dict(\r
+label = _("Contact URL"),\r
+help_text = _("The URL provided for users to contact you. It can be http: or mailto: or whatever your preferred contact scheme is."),\r
+required=False))\r
+\r
+\r
diff --git a/forum/modules/template_loader.py/forum/settings/email.py b/forum/modules/template_loader.py/forum/settings/email.py
new file mode 100644 (file)
index 0000000..5e8bddf
--- /dev/null
@@ -0,0 +1,78 @@
+from base import Setting, SettingSet\r
+from django.utils.translation import ugettext_lazy as _\r
+from django.forms.widgets import PasswordInput\r
+from django.forms.widgets import RadioSelect\r
+\r
+EMAIL_SET = SettingSet('email', _('Email settings'), _("Email server and other email related settings."), 50)\r
+\r
+EMAIL_SUBSCRIBE_CHOICES = (\r
+    ('y', _('Users are subscribed by default')),\r
+    ('n', _('Users are not subscribed by default')),\r
+)\r
+\r
+INITIAL_EMAIL_SUBSCRIBE_OPTION = Setting('INITIAL_EMAIL_SUBSCRIBE_OPTION', 'y', EMAIL_SET, dict(\r
+label = _("Default email subscription"),\r
+widget=RadioSelect,\r
+choices=EMAIL_SUBSCRIBE_CHOICES,\r
+help_text = _("Choose what should be the default email subscription status while registering."),\r
+required=False))\r
+\r
+EMAIL_HOST = Setting('EMAIL_HOST', '', EMAIL_SET, dict(\r
+label = _("Email Server"),\r
+help_text = _("The SMTP server through which your application will be sending emails."),\r
+required=False))\r
+\r
+EMAIL_PORT = Setting('EMAIL_PORT', 25, EMAIL_SET, dict(\r
+label = _("Email Port"),\r
+help_text = _("The port on which your SMTP server is listening to. Usually this is 25, but can be something else."),\r
+required=False))\r
+\r
+EMAIL_HOST_USER = Setting('EMAIL_HOST_USER', '', EMAIL_SET, dict(\r
+label = _("Email User"),\r
+help_text = _("The username for your SMTP connection."),\r
+required=False))\r
+\r
+EMAIL_HOST_PASSWORD = Setting('EMAIL_HOST_PASSWORD', '', EMAIL_SET, dict(\r
+label = _("Email Password"),\r
+help_text = _("The password for your SMTP connection."),\r
+required=False,\r
+widget=PasswordInput))\r
+\r
+EMAIL_USE_TLS = Setting('EMAIL_USE_TLS', False, EMAIL_SET, dict(\r
+label = _("Use TLS"),\r
+help_text = _("Whether to use TLS for authentication with your SMTP server."),\r
+required=False))\r
+\r
+DEFAULT_FROM_EMAIL = Setting('DEFAULT_FROM_EMAIL', '', EMAIL_SET, dict(\r
+label = _("Site 'from' Email Address"),\r
+help_text = _("The address that will show up on the 'from' field on emails sent by your website."),\r
+required=False))\r
+\r
+EMAIL_SUBJECT_PREFIX = Setting('EMAIL_SUBJECT_PREFIX', '', EMAIL_SET, dict(\r
+label = _("Email Subject Prefix"),\r
+help_text = _("Every email sent through your website will have the subject prefixed by this string. It's usually a good idea to have such a prefix so your users can easily set up a filter on theyr email clients."),\r
+required=False))\r
+\r
+EMAIL_FOOTER_TEXT = Setting(u'EMAIL_FOOTER_TEXT', '', EMAIL_SET, dict(\r
+label = _("Email Footer Text"),\r
+help_text = _("Email footer text, usually \"CAN SPAM\" compliance, or the physical address of the organization running the website. See <a href=\"http://en.wikipedia.org/wiki/CAN-SPAM_Act_of_2003\">this Wikipedia article</a> for more info."),\r
+required=False))\r
+\r
+EMAIL_BORDER_COLOR = Setting('EMAIL_BORDER_COLOR', '#e5ebf8', EMAIL_SET, dict(\r
+label = _("Email Border Color"),\r
+help_text = _("The outter border color of the email base template"),\r
+required=False))\r
+\r
+EMAIL_PARAGRAPH_STYLE = Setting('EMAIL_PARAGRAPH_STYLE', "color:#333333;font-family:'helvetica neue', arial, Helvetica, sans-serif;line-height:18px;font-size:14px;margin-top:10px;", EMAIL_SET, dict(\r
+label = _("Email Paragraph Style"),\r
+help_text = _("A valid css string to be used to style email paragraphs (the P tag)."),\r
+required=False))\r
+\r
+EMAIL_ANCHOR_STYLE = Setting('EMAIL_ANCHOR_STYLE', "text-decoration:none;color:#3060a8;font-weight:bold;", EMAIL_SET, dict(\r
+label = _("Email Link Style"),\r
+help_text = _("A valid css string to be used to style email links (the A tag)."),\r
+required=False))\r
+\r
+\r
+\r
+EMAIL_DIGEST_FLAG = Setting('EMAIL_DIGEST_FLAG', None)\r
diff --git a/forum/modules/template_loader.py/forum/settings/extkeys.py b/forum/modules/template_loader.py/forum/settings/extkeys.py
new file mode 100644 (file)
index 0000000..9d439df
--- /dev/null
@@ -0,0 +1,15 @@
+from base import Setting, SettingSet\r
+from django.utils.translation import ugettext_lazy as _\r
+\r
+EXT_KEYS_SET = SettingSet('extkeys', _('External Keys'), _("Keys for various external providers that your application may optionally use."), 100)\r
+\r
+GOOGLE_SITEMAP_CODE = Setting('GOOGLE_SITEMAP_CODE', '', EXT_KEYS_SET, dict(\r
+label = _("Google sitemap code"),\r
+help_text = _("This is the code you get when you register your site at <a href='https://www.google.com/webmasters/tools/'>Google webmaster central</a>."),\r
+required=False))\r
+\r
+GOOGLE_ANALYTICS_KEY = Setting('GOOGLE_ANALYTICS_KEY', '', EXT_KEYS_SET, dict(\r
+label = _("Google analytics key"),\r
+help_text = _("Your Google analytics key. You can get one at the <a href='http://www.google.com/analytics/'>Google analytics official website</a>"),\r
+required=False))\r
+\r
diff --git a/forum/modules/template_loader.py/forum/settings/faq.py b/forum/modules/template_loader.py/forum/settings/faq.py
new file mode 100644 (file)
index 0000000..2be4a13
--- /dev/null
@@ -0,0 +1,61 @@
+from base import Setting, SettingSet
+from django.forms.widgets import Textarea
+
+FAQ_SET = SettingSet('faq', 'FAQ page', "Define the text in the about page. You can use markdown and some basic html tags.", 2000, True)
+
+FAQ_PAGE_TEXT = Setting('FAQ_PAGE_TEXT',
+u"""
+**Please customize this text in the administration area**
+
+**Frequently Asked Questions (FAQ)**
+
+**What kinds of questions can I ask here?**
+
+Most importantly - questions should be relevant to this community. Before you ask - please make sure to search for a similar question. You can search questions by their title or tags.
+
+**What kinds of questions should be avoided?**
+
+Please avoid asking questions that are not relevant to this community, too subjective and argumentative.
+
+**What should I avoid in my answers?**
+
+OSQA: Open Source Q&A Forum is a question and answer site - it is not a discussion group. Please avoid holding debates in your answers as they tend to dilute the essense of questions and answers. For the brief discussions please use commenting facility.
+
+**Who moderates this community?**
+
+The short answer is: you. This website is moderated by the users. Karma system allows users to earn rights to perform a variety of moderation tasks
+
+**How does the karma system work?**
+
+When a question or answer is upvoted, the user who posted them will gain some points, which are called "karma points". These points serve as a rough measure of the community trust to him/her. Various moderation tasks are gradually assigned to the users based on those points.
+
+For example, if you ask an interesting question or give a helpful answer, your input will be upvoted. On the other hand if the answer is misleading - it will be downvoted. Each vote in favor will generate |REP_GAIN_BY_UPVOTED| points, each vote against will subtract |REP_LOST_BY_DOWNVOTED| points. There is a limit of 200 points that can be accumulated per question or answer. The table below explains karma requirements for each type of moderation task.
+
+* add comments ->  |REP_TO_COMMENT|
+* delete comments -> |REP_TO_DELETE_COMMENTS|
+* close own questions -> |REP_TO_CLOSE_OWN|
+* reopen own questions -> |REP_TO_REOPEN_OWN|
+* retag questions -> |REP_TO_RETAG|
+* edit any answer -> |REP_TO_EDIT_OTHERS|
+* open any closed question -> |REP_TO_CLOSE_OTHERS|
+* delete any comment -> |REP_TO_DELETE_COMMENTS|
+
+**What is gravatar?**
+
+Gravatar means globally recognized avatar - your unique avatar image associated with your email address. It's simply a picture that shows next to your posts on the websites that support gravatar protocol. By default gravar appears as a square filled with a snowflake-like figure. You can set your image at gravatar.com
+
+**To register, do I need to create new password?**
+
+No, you don't have to. You can login through any service that supports OpenID, e.g. Google, Yahoo, AOL, etc. Login now!
+
+**Why can other people can edit my questions/answers?**
+
+Goal of this site is... 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. If this approach is not for you, we respect your choice.
+
+**Still have questions?**
+
+Please ask your question, help make our community better!
+""", FAQ_SET, dict(
+label = "FAQ page text",
+help_text = " The faq page. ",
+widget=Textarea(attrs={'rows': '25'})))
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/settings/form.py b/forum/modules/template_loader.py/forum/settings/form.py
new file mode 100644 (file)
index 0000000..5f770b3
--- /dev/null
@@ -0,0 +1,87 @@
+import os.path
+from base import Setting, SettingSet
+from django.utils.translation import ugettext_lazy as _
+
+FORUM_SET = SettingSet('form', _('Form settings'), _("General settings for the OSQA forms."), 10)
+
+WIKI_ON = Setting('WIKI_ON', True, FORUM_SET, dict(
+label = _("Enable community wiki"),
+help_text = _("Can questions or answers be marked as community wiki."),
+required=False))
+
+LIMIT_TAG_CREATION = Setting('LIMIT_TAG_CREATION', False, FORUM_SET, dict(
+label = _("Limit tag creation"),
+help_text = _("Limit tag creation to super users, staff or users with a minimum reputation."),
+required=False))
+
+
+""" settings for questions """
+FORM_MIN_QUESTION_TITLE = Setting('FORM_MIN_QUESTION_TITLE', 10, FORUM_SET, dict(
+label = _("Minimum number of characters for a question's title"),
+help_text = _("The minimum number of characters a user must enter into the title field of a question.")))
+
+# FORM_MAX_QUESTION_TITLE = Setting('FORM_MAX_QUESTION_TITLE', 100, FORUM_SET, dict(
+# label = _("Maximum number of characters for a question."),
+# help_text = _("The maximum number of characters a user can enter into the description field to submit a question.")))
+
+FORM_MIN_QUESTION_BODY = Setting('FORM_MIN_QUESTION_BODY', 10, FORUM_SET, dict(
+label = _("Minimum number of characters for a question's content"),
+help_text = _("The minimum number of characters a user must enter into the content field of a question.")))
+
+# FORM_MAX_QUESTION_DESCRIPTION = Setting('FORM_MAX_QUESTION_DESCRIPTION', 600, FORUM_SET, dict(
+# label = _("Maximum number of characters for a question."),
+# help_text = _("The maximum number of characters a user can enter into the description field to submit a question.")))
+
+FORM_EMPTY_QUESTION_BODY = Setting('FORM_EMPTY_QUESTION_BODY', False, FORUM_SET, dict(
+label = _("Empty question content"),
+help_text = _("If a question's content can be empty."),
+required=False))
+
+
+
+
+""" settings for tags """
+FORM_MIN_NUMBER_OF_TAGS = Setting('FORM_MIN_NUMBER_OF_TAGS', 1, FORUM_SET, dict(
+label = _("Required number of tags per question"),
+help_text = _("How many tags are required in questions."),
+))
+
+FORM_MAX_NUMBER_OF_TAGS = Setting('FORM_MAX_NUMBER_OF_TAGS', 5, FORUM_SET, dict(
+label = _("Maximum number of tags per question"),
+help_text = _("How many tags are allowed in questions."),
+))
+
+FORM_MIN_LENGTH_OF_TAG = Setting('FORM_MIN_LENGTH_OF_TAG', 1, FORUM_SET, dict(
+label = _("Minimum length of a tag"),
+help_text = _("How short a tag can be."),
+))
+
+FORM_MAX_LENGTH_OF_TAG = Setting('FORM_MAX_LENGTH_OF_TAG', 20, FORUM_SET, dict(
+label = _("Maximum length of a tag"),
+help_text = _("How long a tag can be."),
+))
+
+
+
+
+""" settings for comments """
+FORM_MIN_COMMENT_BODY = Setting('FORM_MIN_COMMENT_BODY', 10, FORUM_SET, dict(
+label = _("Minimum number of characters for a comment"),
+help_text = _("The minimum number of characters a user must enter into the body of a comment.")))
+
+FORM_MAX_COMMENT_BODY = Setting('FORM_MAX_COMMENT_BODY', 600, FORUM_SET, dict(
+label = _("Maximum length of comment"),
+help_text = _("The maximum number of characters a user can enter into the body of a comment.")))
+
+FORM_ALLOW_MARKDOWN_IN_COMMENTS = Setting('FORM_ALLOW_MARKDOWN_IN_COMMENTS', True, FORUM_SET, dict(
+label = _("Allow markdown in comments"),
+help_text = _("Allow users to use markdown in comments."),
+required=False))
+
+FORM_GRAVATAR_IN_COMMENTS = Setting('FORM_GRAVATAR_IN_COMMENTS', False, FORUM_SET, dict(
+label = _("Show author gravatar in comments"),
+help_text = _("Show the gravatar image of a comment author."),
+required=False))
+
+
+
diff --git a/forum/modules/template_loader.py/forum/settings/forms.py b/forum/modules/template_loader.py/forum/settings/forms.py
new file mode 100644 (file)
index 0000000..0c12301
--- /dev/null
@@ -0,0 +1,126 @@
+import os
+from string import strip
+from django import forms
+from forum.settings.base import Setting
+from django.utils.translation import ugettext as _
+from django.core.files.storage import FileSystemStorage
+
+class DummySetting:
+    pass
+
+class UnfilteredField(forms.CharField):
+    def clean(self, value):
+            return value
+
+
+class SettingsSetForm(forms.Form):
+    def __init__(self, set, data=None, unsaved=None, *args, **kwargs):
+        initial = dict([(setting.name, setting.value) for setting in set])
+
+        if unsaved:
+            initial.update(unsaved)
+
+        super(SettingsSetForm, self).__init__(data, initial=initial, *args, **kwargs)
+
+        for setting in set:
+            widget = setting.field_context.get('widget', None)
+
+            if widget is forms.CheckboxSelectMultiple or widget is forms.SelectMultiple or isinstance(widget, forms.SelectMultiple):
+                field = forms.MultipleChoiceField(**setting.field_context)
+            elif widget is forms.RadioSelect or isinstance(widget, forms.RadioSelect):
+                field = forms.ChoiceField(**setting.field_context)
+            elif isinstance(setting, (Setting.emulators.get(str, DummySetting), Setting.emulators.get(unicode, DummySetting))):
+                if not setting.field_context.get('widget', None):
+                    setting.field_context['widget'] = forms.TextInput(attrs={'class': 'longstring'})
+                field = forms.CharField(**setting.field_context)
+            elif isinstance(setting, Setting.emulators.get(float, DummySetting)):
+                field = forms.FloatField(**setting.field_context)
+            elif isinstance(setting, Setting.emulators.get(int, DummySetting)):
+                field = forms.IntegerField(**setting.field_context)
+            elif isinstance(setting, Setting.emulators.get(bool, DummySetting)):
+                field = forms.BooleanField(**setting.field_context)
+            else:
+                field = UnfilteredField(**setting.field_context)
+
+            self.fields[setting.name] = field
+
+        self.set = set
+
+    def as_table(self):
+        return self._html_output(
+                u'<tr><th>%(label)s' + ('<br /><a class="fieldtool context" href="#">%s</a><span class="sep">|</span><a class="fieldtool default" href="#">%s</a></th>' % (
+                    _('context'), _('default'))) + u'<td>%(errors)s%(field)s%(help_text)s</td>',
+                u'<tr><td colspan="2">%s</td></tr>', '</td></tr>', u'<br />%s', False)
+
+    def save(self):
+        for setting in self.set:
+            setting.set_value(self.cleaned_data[setting.name])
+
+class ImageFormWidget(forms.Widget):
+    def render(self, name, value, attrs=None):
+        return """
+            <img src="%(value)s" /><br />
+            %(change)s: <input type="file" name="%(name)s" />
+            <input type="hidden" name="%(name)s_old" value="%(value)s" />
+            """ % {'name': name, 'value': value, 'change': _('Change this:')}
+
+    def value_from_datadict(self, data, files, name):
+        if name in files:
+            f = files[name]
+
+            # check file type
+            file_name_suffix = os.path.splitext(f.name)[1].lower()
+
+            if not file_name_suffix in ('.jpg', '.jpeg', '.gif', '.png', '.bmp', '.tiff', '.ico'):
+                raise Exception('File type not allowed')
+
+            from forum.settings import UPFILES_FOLDER, UPFILES_ALIAS
+
+            storage = FileSystemStorage(str(UPFILES_FOLDER), str(UPFILES_ALIAS))
+            new_file_name = storage.save(f.name, f)
+            return str(UPFILES_ALIAS) + new_file_name
+        else:
+            if "%s_old" % name in data:
+                return data["%s_old" % name]
+            elif name in data:
+                return data[name]
+
+class StringListWidget(forms.Widget):
+    def render(self, name, value, attrs=None):
+        ret = ""
+        for s in value:
+            ret += """
+            <div class="string-list-input">
+                <input type="text" name="%(name)s" value="%(value)s" />
+                <button class="string_list_widget_button">-</button>
+            </div>
+            """  % {'name': name, 'value': s}
+
+        return """
+            <div class="string_list_widgets">
+                %(ret)s
+                <div><button name="%(name)s" class="string_list_widget_button add">+</button></div>
+            </div>
+            """ % dict(name=name, ret=ret)
+
+    def value_from_datadict(self, data, files, name):
+        if 'submit' in data:
+            return data.getlist(name)
+        else:
+            return data[name]
+
+class CommaStringListWidget(forms.Textarea):
+    def render(self, name, value, attrs=None):
+        return super(CommaStringListWidget, self).render(name, ', '.join(value), attrs)
+
+
+    def value_from_datadict(self, data, files, name):
+        if 'submit' in data:
+            return map(strip, data[name].split(','))
+        else:
+            return ', '.join(data[name])    
+
+
+
+
+
diff --git a/forum/modules/template_loader.py/forum/settings/minrep.py b/forum/modules/template_loader.py/forum/settings/minrep.py
new file mode 100644 (file)
index 0000000..8206823
--- /dev/null
@@ -0,0 +1,90 @@
+from base import Setting, SettingSet\r
+from django.utils.translation import ugettext_lazy as _\r
+\r
+MIN_REP_SET = SettingSet('minrep', _('Minimum reputation config'), _("Configure the minimum reputation required to perform certain actions on your site."), 300)\r
+\r
+CAPTCHA_IF_REP_LESS_THAN = Setting('CAPTCHA_IF_REP_LESS_THAN', 0, MIN_REP_SET, dict(\r
+label = _("Show captcha if user with less reputation than"),\r
+help_text = _("If the user has less reputation, captcha is used to when adding new content.")))\r
+\r
+REP_TO_VOTE_UP = Setting('REP_TO_VOTE_UP', 15, MIN_REP_SET, dict(\r
+label = _("Minimum reputation to vote up"),\r
+help_text = _("The minimum reputation an user must have to be allowed to vote up.")))\r
+\r
+REP_TO_VOTE_DOWN = Setting('REP_TO_VOTE_DOWN', 100, MIN_REP_SET, dict(\r
+label = _("Minimum reputation to vote down"),\r
+help_text = _("The minimum reputation an user must have to be allowed to vote down.")))\r
+\r
+REP_TO_FLAG = Setting('REP_TO_FLAG', 15, MIN_REP_SET, dict(\r
+label = _("Minimum reputation to flag a post"),\r
+help_text = _("The minimum reputation an user must have to be allowed to flag a post.")))\r
+\r
+REP_TO_COMMENT = Setting('REP_TO_COMMENT', 50, MIN_REP_SET, dict(\r
+label = _("Minimum reputation to comment"),\r
+help_text = _("The minimum reputation an user must have to be allowed to comment a post.")))\r
+\r
+REP_TO_LIKE_COMMENT = Setting('REP_TO_LIKE_COMMENT', 15, MIN_REP_SET, dict(\r
+label = _("Minimum reputation to like a comment"),\r
+help_text = _("The minimum reputation an user must have to be allowed to \"like\" a comment.")))\r
+\r
+REP_TO_UPLOAD = Setting('REP_TO_UPLOAD', 60, MIN_REP_SET, dict(\r
+label = _("Minimum reputation to upload"),\r
+help_text = _("The minimum reputation an user must have to be allowed to upload a file.")))\r
+\r
+REP_TO_CREATE_TAGS = Setting('REP_TO_CREATE_TAGS', 250, MIN_REP_SET, dict(\r
+label = _("Minimum reputation to create tags"),\r
+help_text = _("The minimum reputation an user must have to be allowed to create new tags.")))\r
+\r
+REP_TO_CLOSE_OWN = Setting('REP_TO_CLOSE_OWN', 250, MIN_REP_SET, dict(\r
+label = _("Minimum reputation to close own question"),\r
+help_text = _("The minimum reputation an user must have to be allowed to close his own question.")))\r
+\r
+REP_TO_REOPEN_OWN = Setting('REP_TO_REOPEN_OWN', 500, MIN_REP_SET, dict(\r
+label = _("Minimum reputation to reopen own question"),\r
+help_text = _("The minimum reputation an user must have to be allowed to reopen his own question.")))\r
+\r
+REP_TO_RETAG = Setting('REP_TO_RETAG', 500, MIN_REP_SET, dict(\r
+label = _("Minimum reputation to retag others questions"),\r
+help_text = _("The minimum reputation an user must have to be allowed to retag others questions.")))\r
+\r
+REP_TO_EDIT_WIKI = Setting('REP_TO_EDIT_WIKI', 750, MIN_REP_SET, dict(\r
+label = _("Minimum reputation to edit wiki posts"),\r
+help_text = _("The minimum reputation an user must have to be allowed to edit community wiki posts.")))\r
+\r
+REP_TO_WIKIFY = Setting('REP_TO_WIKIFY', 2000, MIN_REP_SET, dict(\r
+label = _("Minimum reputation to mark post as community wiki"),\r
+help_text = _("The minimum reputation an user must have to be allowed to mark a post as community wiki.")))\r
+\r
+REP_TO_EDIT_OTHERS = Setting('REP_TO_EDIT_OTHERS', 2000, MIN_REP_SET, dict(\r
+label = _("Minimum reputation to edit others posts"),\r
+help_text = _("The minimum reputation an user must have to be allowed to edit others posts.")))\r
+\r
+REP_TO_CLOSE_OTHERS = Setting('REP_TO_CLOSE_OTHERS', 3000, MIN_REP_SET, dict(\r
+label = _("Minimum reputation to close others posts"),\r
+help_text = _("The minimum reputation an user must have to be allowed to close others posts.")))\r
+\r
+REP_TO_DELETE_COMMENTS = Setting('REP_TO_DELETE_COMMENTS', 2000, MIN_REP_SET, dict(\r
+label = _("Minimum reputation to delete comments"),\r
+help_text = _("The minimum reputation an user must have to be allowed to delete comments.")))\r
+\r
+REP_TO_CONVERT_TO_COMMENT = Setting('REP_TO_CONVERT_TO_COMMENT', 2000, MIN_REP_SET, dict(\r
+label = _("Minimum reputation to convert answers to comment"),\r
+help_text = _("The minimum reputation an user must have to be allowed to convert an answer into a comment.")))\r
+\r
+REP_TO_CONVERT_COMMENTS_TO_ANSWERS = Setting('REP_TO_CONVERT_COMMENTS_TO_ANSWERS', 2000, MIN_REP_SET, dict(\r
+label = _("Minimum reputation to convert comments to answers"),\r
+help_text = _("The minimum reputation an user must have to be allowed to convert comments into an answer.")))\r
+\r
+REP_TO_CONVERT_TO_QUESTION = Setting('REP_TO_CONVERT_TO_QUESTION', 2000, MIN_REP_SET, dict(\r
+label = _("Minimum reputation to convert answers to questions"),\r
+help_text = _("The minimum reputation an user must have to be allowed to convert an answer into a question.")))\r
+\r
+REP_TO_VIEW_FLAGS = Setting('REP_TO_VIEW_FLAGS', 2000, MIN_REP_SET, dict(\r
+label = _("Minimum reputation to view offensive flags"),\r
+help_text = _("The minimum reputation an user must have to view offensive flags.")))\r
+\r
+#REP_TO_DISABLE_NOFOLLOW = Setting('REP_TO_DISABLE_NOFOLLOW', 2000, MIN_REP_SET, dict(\r
+#label = _("Minimum reputation to disable nofollow"),\r
+#help_text = _("""\r
+#The minimum reputation an user must have to be allowed to disable the nofollow attribute of a post link.\r
+#""")))\r
diff --git a/forum/modules/template_loader.py/forum/settings/moderation.py b/forum/modules/template_loader.py/forum/settings/moderation.py
new file mode 100644 (file)
index 0000000..6af5401
--- /dev/null
@@ -0,0 +1,24 @@
+from base import Setting, SettingSet
+from forms import StringListWidget
+
+from django.utils.translation import ugettext_lazy as _
+from django.forms.widgets import Textarea
+
+MODERATION_SET = SettingSet('moderation', _('Moderation settings'), _("Define the moderation workflow of your site"), 100)
+
+FLAG_TYPES = Setting('FLAG_TYPES',
+["Spam", "Advertising", "Offensive, Abusive, or Inappropriate", "Content violates terms of use", "Copyright Violation",
+ "Misleading", "Someone is not being nice", "Not relevant/off-topic", "Other"],
+MODERATION_SET, dict(
+label = _("Flag Reasons"),
+help_text = _("Create some flag reasons to use in the flag post popup."),
+widget=StringListWidget))
+
+
+CLOSE_TYPES = Setting('CLOSE_TYPES',
+["Duplicate Question", "Question is off-topic or not relevant", "Too subjective and argumentative",
+ "The question is answered, right answer was accepted", "Problem is not reproducible or outdated", "Other"],
+MODERATION_SET, dict(
+label = _("Close Reasons"),
+help_text = _("Create some close reasons to use in the close question popup."),
+widget=StringListWidget))
diff --git a/forum/modules/template_loader.py/forum/settings/repgain.py b/forum/modules/template_loader.py/forum/settings/repgain.py
new file mode 100644 (file)
index 0000000..cfb566b
--- /dev/null
@@ -0,0 +1,45 @@
+from base import Setting, SettingSet\r
+from django.utils.translation import ugettext_lazy as _\r
+\r
+REP_GAIN_SET = SettingSet('repgain', _('Reputation gains and losses config'), _("Configure the reputation points a user may gain or lose upon certain actions."), 200)\r
+\r
+INITIAL_REP = Setting('INITIAL_REP', 1, REP_GAIN_SET, dict(\r
+label = _("Initial reputation"),\r
+help_text = _("The initial reputation an user gets when he first signs in.")))\r
+\r
+MAX_REP_BY_UPVOTE_DAY = Setting('MAX_REP_BY_UPVOTE_DAY', 200, REP_GAIN_SET, dict(\r
+label = "Max rep by up votes / day",\r
+help_text = _("Maximum reputation a user can gain in one day for being upvoted.")))\r
+\r
+REP_GAIN_BY_UPVOTED = Setting('REP_GAIN_BY_UPVOTED', 10, REP_GAIN_SET, dict(\r
+label = _("Rep gain by upvoted"),\r
+help_text = _("Reputation a user gains for having one of his posts up voted.")))\r
+\r
+REP_LOST_BY_DOWNVOTED = Setting('REP_LOST_BY_DOWNVOTED', 2, REP_GAIN_SET, dict(\r
+label = _("Rep lost by downvoted"),\r
+help_text = _("Reputation a user loses for having one of his posts down voted.")))\r
+\r
+REP_LOST_BY_DOWNVOTING = Setting('REP_LOST_BY_DOWNVOTING', 1, REP_GAIN_SET, dict(\r
+label = _("Rep lost by downvoting"),\r
+help_text = _("Reputation a user loses for down voting a post.")))\r
+\r
+\r
+REP_GAIN_BY_ACCEPTED = Setting('REP_GAIN_BY_ACCEPTED', 15, REP_GAIN_SET, dict(\r
+label = _("Rep gain by accepted answer"),\r
+help_text = _("Reputation a user gains for having one of his answers accepted.")))\r
+\r
+REP_GAIN_BY_ACCEPTING = Setting('REP_GAIN_BY_ACCEPTING', 2, REP_GAIN_SET, dict(\r
+label = _("Rep gain by accepting answer"),\r
+help_text = _("Reputation a user gains for accepting an answer to one of his questions.")))\r
+\r
+REP_LOST_BY_FLAGGED = Setting('REP_LOST_BY_FLAGGED', 2, REP_GAIN_SET, dict(\r
+label = _("Rep lost by post flagged"),\r
+help_text = _("Reputation a user loses by having one of his posts flagged.")))\r
+\r
+REP_LOST_BY_FLAGGED_3_TIMES = Setting('REP_LOST_BY_FLAGGED_3_TIMES', 30, REP_GAIN_SET, dict(\r
+label = _("Rep lost by post flagged and hidden"),\r
+help_text = _("Reputation a user loses by having the last revision of one of his posts flagged the enough number of times to hide the post.")))\r
+\r
+REP_LOST_BY_FLAGGED_5_TIMES = Setting('REP_LOST_BY_FLAGGED_5_TIMES', 100, REP_GAIN_SET, dict(\r
+label = _("Rep lost by post flagged and deleted"),\r
+help_text = _("Reputation a user loses by having the last revision of one of his posts flagged the enough number of times to delete the post.")))
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/settings/sidebar.py b/forum/modules/template_loader.py/forum/settings/sidebar.py
new file mode 100644 (file)
index 0000000..ee75293
--- /dev/null
@@ -0,0 +1,78 @@
+from base import Setting, SettingSet
+from django.forms.widgets import Textarea, Select
+from django.utils.translation import ugettext_lazy as _
+
+from static import RENDER_CHOICES
+
+SIDEBAR_SET = SettingSet('sidebar', 'Sidebar content', "Enter contents to display in the sidebar. You can use markdown and some basic html tags.", 10, True)
+
+SHOW_WELCOME_BOX = Setting('SHOW_WELCOME_BOX', True, SIDEBAR_SET, dict(
+label = _("Show the Welcome box"),
+help_text = _("Do you want to show the welcome box when a user first visits your site."),
+required=False))
+
+APP_INTRO = Setting('APP_INTRO', u'<p>Ask and answer questions, make the world better!</p>', SIDEBAR_SET, dict(
+label = _("Application intro"),
+help_text = _("The introductory page that is visible in the sidebar for anonymous users."),
+widget=Textarea))
+
+
+SIDEBAR_UPPER_SHOW = Setting('SIDEBAR_UPPER_SHOW', True, SIDEBAR_SET, dict(
+label = "Show Upper Block",
+help_text = "Check if your pages should display the upper sidebar block.",
+required=False))
+
+SIDEBAR_UPPER_DONT_WRAP = Setting('SIDEBAR_UPPER_DONT_WRAP', False, SIDEBAR_SET, dict(
+label = "Don't Wrap Upper Block",
+help_text = "Don't wrap upper block with the standard style.",
+required=False))
+
+SIDEBAR_UPPER_TEXT = Setting('SIDEBAR_UPPER_TEXT',
+u"""
+[![WebFaction logo][2]][1]
+## [Reliable OSQA Hosting][1]
+
+We recommend [**WebFaction**][1] for OSQA hosting. For \
+under $10/month their reliable servers get the job done. See our \
+[**step-by-step setup guide**](http://wiki.osqa.net/display/docs/Installing+OSQA+on+WebFaction).
+
+[1]: http://www.webfaction.com?affiliate=osqa
+[2]: /m/default/media/images/webfaction.png""", SIDEBAR_SET, dict(
+label = "Upper Block Content",
+help_text = " The upper sidebar block. ",
+widget=Textarea(attrs={'rows': '10'})))
+
+SIDEBAR_UPPER_RENDER_MODE = Setting('SIDEBAR_UPPER_RENDER_MODE', 'markdown', SIDEBAR_SET, dict(
+label = _("Upper block rendering mode"),
+help_text = _("How to render your upper block code."),
+widget=Select(choices=RENDER_CHOICES),
+required=False))
+
+
+SIDEBAR_LOWER_SHOW = Setting('SIDEBAR_LOWER_SHOW', True, SIDEBAR_SET, dict(
+label = "Show Lower Block",
+help_text = "Check if your pages should display the lower sidebar block.",
+required=False))
+
+SIDEBAR_LOWER_DONT_WRAP = Setting('SIDEBAR_LOWER_DONT_WRAP', False, SIDEBAR_SET, dict(
+label = "Don't Wrap Lower Block",
+help_text = "Don't wrap lower block with the standard style.",
+required=False))
+
+SIDEBAR_LOWER_TEXT = Setting('SIDEBAR_LOWER_TEXT',
+u"""
+## Learn more about OSQA
+
+The [**OSQA website**](http://www.osqa.net/) and [**OSQA wiki**](http://wiki.osqa.net/) \
+are great resources to help you learn more about the OSQA open source Q&A system. \
+[**Join the OSQA chat!**](http://meta.osqa.net/question/79/is-there-an-online-chat-room-or-irc-channel-for-osqa#302)
+""", SIDEBAR_SET, dict(
+label = "Lower Block Content",
+help_text = " The lower sidebar block. ",
+widget=Textarea(attrs={'rows': '10'})))
+
+SIDEBAR_LOWER_RENDER_MODE = Setting('SIDEBAR_LOWER_RENDER_MODE', 'markdown', SIDEBAR_SET, dict(
+label = _("Lower block rendering mode"),
+help_text = _("How to render your lower block code."),
+widget=Select(choices=RENDER_CHOICES),
+required=False))
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/settings/static.py b/forum/modules/template_loader.py/forum/settings/static.py
new file mode 100644 (file)
index 0000000..9eb5d39
--- /dev/null
@@ -0,0 +1,106 @@
+from base import Setting, SettingSet
+from django.forms.widgets import Textarea, RadioSelect, Select
+from django.utils.translation import ugettext_lazy as _
+
+RENDER_CHOICES = (
+('markdown', _('Markdown')),
+('html', _('HTML')),
+('escape', _('Escaped'))
+)
+
+STATIC_PAGE_REGISTRY = Setting('STATIC_PAGE_REGISTRY', {})
+
+CSS_SET = SettingSet('css', 'Custom CSS', "Define some custom css you can use to override the default css.", 2000,
+                     can_preview=True)
+
+USE_CUSTOM_CSS = Setting('USE_CUSTOM_CSS', False, CSS_SET, dict(
+        label = _("Use custom CSS"),
+        help_text = _("Do you want to use custom CSS."),
+        required=False))
+
+CUSTOM_CSS = Setting('CUSTOM_CSS', '', CSS_SET, dict(
+        label = _("Custom CSS"),
+        help_text = _("Your custom CSS."),
+        widget=Textarea(attrs={'rows': '25'}),
+        required=False))
+
+HEAD_AND_FOOT_SET = SettingSet('headandfoot', 'Header and Footer', "Adds a custom header and/or footer to your page",
+                               2000, can_preview=True)
+
+USE_CUSTOM_HEADER = Setting('USE_CUSTOM_HEADER', False, HEAD_AND_FOOT_SET, dict(
+        label = _("Use custom header"),
+        help_text = _("Do you want to use a custom header."),
+        required=False))
+
+CUSTOM_HEADER = Setting('CUSTOM_HEADER', '', HEAD_AND_FOOT_SET, dict(
+        label = _("Custom Header"),
+        help_text = _("Your custom header."),
+        widget=Textarea(attrs={'rows': '25'}),
+        required=False))
+
+CUSTOM_HEADER_RENDER_MODE = Setting('CUSTOM_HEADER_RENDER_MODE', 'markdown', HEAD_AND_FOOT_SET, dict(
+        label = _("Custom Header rendering mode"),
+        help_text = _("How to render your custom header code."),
+        widget=Select(choices=RENDER_CHOICES),
+        required=False))
+
+USE_ANNOUNCEMENT_BAR = Setting('USE_ANNOUNCEMENT_BAR', False, HEAD_AND_FOOT_SET, dict(
+        label = _("Show announcement bar"),
+        help_text = _("Some piece of content that goes under the search bar and can be used for announcements, etc."),
+        required=False))
+
+ANNOUNCEMENT_BAR = Setting('ANNOUNCEMENT_BAR', '', HEAD_AND_FOOT_SET, dict(
+        label = _("Announcement bar"),
+        help_text = _("The announcement bar content."),
+        widget=Textarea(attrs={'rows': '25'}),
+        required=False))
+
+ANNOUNCEMENT_BAR_RENDER_MODE = Setting('ANNOUNCEMENT_BAR_RENDER_MODE', 'markdown', HEAD_AND_FOOT_SET, dict(
+        label = _("Announcement bar rendering mode"),
+        help_text = _("How to render your announcement bar code."),
+        widget=Select(choices=RENDER_CHOICES),
+        required=False))
+
+USE_CUSTOM_FOOTER = Setting('USE_CUSTOM_FOOTER', False, HEAD_AND_FOOT_SET, dict(
+        label = _("Use custom footer"),
+        help_text = _("Do you want to use a custom footer."),
+        required=False))
+
+CUSTOM_FOOTER = Setting('CUSTOM_FOOTER', '', HEAD_AND_FOOT_SET, dict(
+        label = _("Custom Footer"),
+        help_text = _("Your custom footer."),
+        widget=Textarea(attrs={'rows': '25'}),
+        required=False))
+
+CUSTOM_FOOTER_RENDER_MODE = Setting('CUSTOM_FOOTER_RENDER_MODE', 'markdown', HEAD_AND_FOOT_SET, dict(
+        label = _("Custom footer rendering mode"),
+        help_text = _("How to render your custom footer code."),
+        widget=Select(choices=RENDER_CHOICES),
+        required=False))
+
+CUSTOM_FOOTER_MODE_CHOICES = (
+('replace', _('Replace default footer')),
+('above', _('Above default footer')),
+('below', _('Below default footer')),
+)
+
+CUSTOM_FOOTER_MODE = Setting('CUSTOM_FOOTER_MODE', 'replace', HEAD_AND_FOOT_SET, dict(
+        label = _("Custom Footer Mode"),
+        help_text = _("How your custom footer will appear."),
+        widget=RadioSelect,
+        choices=CUSTOM_FOOTER_MODE_CHOICES,
+        required=False))
+
+HEAD_SET = SettingSet('head', '<head>', "Define some custom elements to include in the head section of every page.",
+                      2000, can_preview=True)
+
+USE_CUSTOM_HEAD = Setting('USE_CUSTOM_HEAD', False, HEAD_SET, dict(
+        label = _("Use custom Head elements"),
+        help_text = _("Do you want to use custom head elements."),
+        required=False))
+
+CUSTOM_HEAD = Setting('CUSTOM_HEAD', '', HEAD_SET, dict(
+        label = _("Custom Head"),
+        help_text = _("Your custom Head elements."),
+        widget=Textarea(attrs={'rows': '25'}),
+        required=False))
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/settings/upload.py b/forum/modules/template_loader.py/forum/settings/upload.py
new file mode 100644 (file)
index 0000000..6e66e00
--- /dev/null
@@ -0,0 +1,17 @@
+import os.path\r
+from base import Setting, SettingSet\r
+from django.utils.translation import ugettext_lazy as _\r
+\r
+UPLOAD_SET = SettingSet('paths', _('File upload settings'), _("File uploads related settings."), 600)\r
+\r
+UPFILES_FOLDER = Setting('UPFILES_FOLDER', os.path.join(os.path.dirname(os.path.dirname(__file__)),'upfiles'), UPLOAD_SET, dict(\r
+label = _("Uploaded files folder"),\r
+help_text = _("The filesystem path where uploaded files will be stored. Please note that this folder must exist.")))\r
+\r
+UPFILES_ALIAS = Setting('UPFILES_ALIAS', '/upfiles/', UPLOAD_SET, dict(\r
+label = _("Uploaded files alias"),\r
+help_text = _("The url alias for uploaded files. Notice that if you change this setting, you'll need to restart your site.")))\r
+\r
+ALLOW_MAX_FILE_SIZE = Setting('ALLOW_MAX_FILE_SIZE', 2.5, UPLOAD_SET, dict(\r
+label = _("Max file size"),\r
+help_text = _("The maximum allowed file size for uploads in mb.")))
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/settings/urls.py b/forum/modules/template_loader.py/forum/settings/urls.py
new file mode 100644 (file)
index 0000000..e532c55
--- /dev/null
@@ -0,0 +1,15 @@
+from base import Setting, SettingSet
+from django.utils.translation import ugettext as _
+
+URLS_SET = SettingSet('urls', _('URL settings'), _("Some settings to tweak behaviour of site urls (experimental)."))
+
+ALLOW_UNICODE_IN_SLUGS = Setting('ALLOW_UNICODE_IN_SLUGS', False, URLS_SET, dict(
+label = _("Allow unicode in slugs"),
+help_text = _("Allow unicode/non-latin characters in urls."),
+required=False))
+
+FORCE_SINGLE_URL = Setting('FORCE_SINGLE_URL', True, URLS_SET, dict(
+label = _("Force single url"),
+help_text = _("Redirect the request in case there is a mismatch between the slug in the url and the actual slug"),
+required=False))
+
diff --git a/forum/modules/template_loader.py/forum/settings/users.py b/forum/modules/template_loader.py/forum/settings/users.py
new file mode 100644 (file)
index 0000000..040e8eb
--- /dev/null
@@ -0,0 +1,86 @@
+from forms import CommaStringListWidget
+from django.forms import CheckboxSelectMultiple
+from django.forms.widgets import RadioSelect
+from base import Setting, SettingSet
+from django.utils.translation import ugettext as _
+
+USERS_SET = SettingSet('users', _('Users settings'), _("General settings for the OSQA users."), 20)
+
+EDITABLE_SCREEN_NAME = Setting('EDITABLE_SCREEN_NAME', False, USERS_SET, dict(
+label = _("Editable screen name"),
+help_text = _("Allow users to alter their screen name."),
+required=False))
+
+MIN_USERNAME_LENGTH = Setting('MIN_USERNAME_LENGTH', 3, USERS_SET, dict(
+label = _("Minimum username length"),
+help_text = _("The minimum length (in character) of a username.")))
+
+RESERVED_USERNAMES = Setting('RESERVED_USERNAMES',
+[_('fuck'), _('shit'), _('ass'), _('sex'), _('add'), _('edit'), _('save'), _('delete'), _('manage'), _('update'), _('remove'), _('new')]
+, USERS_SET, dict(
+label = _("Disabled usernames"),
+help_text = _("A comma separated list of disabled usernames (usernames not allowed during a new user registration)."),
+widget=CommaStringListWidget))
+
+SHOW_STATUS_DIAMONDS = Setting('SHOW_STATUS_DIAMONDS', True, USERS_SET, dict(
+label=_("Show status diamonds"),
+help_text = _("Show status \"diamonds\" next to moderators or superusers usernames."),
+required=False,
+))
+
+EMAIL_UNIQUE = Setting('EMAIL_UNIQUE', True, USERS_SET, dict(
+label = _("Force unique email"),
+help_text = _("Should each user have an unique email."),
+required=False))
+
+REQUIRE_EMAIL_VALIDATION_TO = Setting('REQUIRE_EMAIL_VALIDATION_TO', [], USERS_SET, dict(
+label = _("Require email validation to..."),
+help_text = _("Which actions in this site, users without a valid email will be prevented from doing."),
+widget=CheckboxSelectMultiple,
+choices=(("ask", _("ask questions")), ("answer", _("provide answers")), ("comment", _("make comments")), ("flag", _("report posts"))),
+required=False,
+))
+
+DONT_NOTIFY_UNVALIDATED = Setting('DONT_NOTIFY_UNVALIDATED', True, USERS_SET, dict(
+label = _("Don't notify to invalid emails"),
+help_text = _("Do not notify users with unvalidated emails."),
+required=False))
+
+HOLD_PENDING_POSTS_MINUTES = Setting('HOLD_PENDING_POSTS_MINUTES', 120, USERS_SET, dict(
+label=_("Hold pending posts for X minutes"),
+help_text=_("How much time in minutes a post should be kept in session until the user logs in or validates the email.")
+))
+
+WARN_PENDING_POSTS_MINUTES = Setting('WARN_PENDING_POSTS_MINUTES', 15, USERS_SET, dict(
+label=_("Warn about pending posts afer X minutes"),
+help_text=_("How much time in minutes a user that just logged in or validated his email should be warned about a pending post instead of publishing it automatically.")
+))
+
+GRAVATAR_RATING_CHOICES = (
+    ('g', _('suitable for display on all websites with any audience type.')),
+    ('pg', _('may contain rude gestures, provocatively dressed individuals, the lesser swear words, or mild violence.')),
+    ('r', _('may contain such things as harsh profanity, intense violence, nudity, or hard drug use.')),
+    ('x', _('may contain hardcore sexual imagery or extremely disturbing violence.')),
+)
+
+GRAVATAR_ALLOWED_RATING = Setting('GRAVATAR_ALLOWED_RATING', 'g', USERS_SET, dict(
+label = _("Gravatar rating"),
+help_text = _("Gravatar allows users to self-rate their images so that they can indicate if an image is appropriate for a certain audience."),
+widget=RadioSelect,
+choices=GRAVATAR_RATING_CHOICES,
+required=False))
+
+GRAVATAR_DEFAULT_CHOICES = (
+    ('mm', _('(mystery-man) a simple, cartoon-style silhouetted outline of a person (does not vary by email hash)')),
+    ('identicon', _('a geometric pattern based on an email hash')),
+    ('monsterid', _('a generated "monster" with different colors, faces, etc')),
+    ('wavatar', _('generated faces with differing features and backgrounds')),
+)
+
+GRAVATAR_DEFAULT_IMAGE = Setting('GRAVATAR_DEFAULT_IMAGE', 'identicon', USERS_SET, dict(
+label = _("Gravatar default"),
+help_text = _("Gravatar has a number of built in options which you can also use as defaults."),
+widget=RadioSelect,
+choices=GRAVATAR_DEFAULT_CHOICES,
+required=False))
+
diff --git a/forum/modules/template_loader.py/forum/settings/view.py b/forum/modules/template_loader.py/forum/settings/view.py
new file mode 100644 (file)
index 0000000..1eb44b0
--- /dev/null
@@ -0,0 +1,17 @@
+from base import Setting, SettingSet
+from django.utils.translation import ugettext_lazy as _
+
+""" view settings """
+VIEW_SET = SettingSet('view', _('View settings'), _("Set up how certain parts of the site are displayed."), 20)
+
+RECENT_TAGS_SIZE = Setting('RECENT_TAGS_SIZE', 25, VIEW_SET, dict(
+label = _("Recent tags block size"),
+help_text = _("The number of tags to display in the recent tags block in the front page.")))
+
+RECENT_AWARD_SIZE = Setting('RECENT_AWARD_SIZE', 15, VIEW_SET, dict(
+label = _("Recent awards block size"),
+help_text = _("The number of awards to display in the recent awards block in the front page.")))
+
+LIMIT_RELATED_TAGS = Setting('LIMIT_RELATED_TAGS', 0, VIEW_SET, dict(
+label = _("Limit related tags block"),
+help_text = _("Limit related tags block size in questions list pages. Set to 0 to display all all tags.")))
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/settings/voting.py b/forum/modules/template_loader.py/forum/settings/voting.py
new file mode 100644 (file)
index 0000000..aea9153
--- /dev/null
@@ -0,0 +1,32 @@
+from base import Setting, SettingSet\r
+from django.utils.translation import ugettext_lazy as _\r
+\r
+VOTE_RULES_SET = SettingSet('voting', _('Voting rules'), _("Configure the voting rules on your site."), 400)\r
+\r
+USER_REPUTATION_TO_MAX_VOTES = Setting('USER_REPUTATION_TO_MAX_VOTES', True, VOTE_RULES_SET, dict(\r
+label = _("Add reputation to max votes per day"), required=False,\r
+help_text = _("The user reputation is added to the static MAX_VOTES_PER_DAY option. Users with higher reputation can vote more.")))\r
+\r
+MAX_VOTES_PER_DAY = Setting('MAX_VOTES_PER_DAY', 30, VOTE_RULES_SET, dict(\r
+label = _("Maximum votes per day"),\r
+help_text = _("The maximum number of votes an user can cast per day.")))\r
+\r
+START_WARN_VOTES_LEFT = Setting('START_WARN_VOTES_LEFT', 10, VOTE_RULES_SET, dict(\r
+label = _("Start warning about votes left"),\r
+help_text = _("From how many votes left should an user start to be warned about it.")))\r
+\r
+MAX_FLAGS_PER_DAY = Setting('MAX_FLAGS_PER_DAY', 5, VOTE_RULES_SET, dict(\r
+label = _("Maximum flags per day"),\r
+help_text = _("The maximum number of times an can flag a post per day.")))\r
+\r
+FLAG_COUNT_TO_HIDE_POST = Setting('FLAG_COUNT_TO_HIDE_POST', 3, VOTE_RULES_SET, dict(\r
+label = _("Flag count to hide post"),\r
+help_text = _("How many times a post needs to be flagged to be hidden from the main page.")))\r
+\r
+FLAG_COUNT_TO_DELETE_POST = Setting('FLAG_COUNT_TO_DELETE_POST', 5, VOTE_RULES_SET, dict(\r
+label = _("Flag count to delete post"),\r
+help_text = _("How many times a post needs to be flagged to be deleted.")))\r
+\r
+DENY_UNVOTE_DAYS = Setting('DENY_UNVOTE_DAYS', 1, VOTE_RULES_SET, dict(\r
+label = _("Days to cancel a vote"),\r
+help_text = _("How many days an user can cancel a vote after he originaly casted it.")))
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/sitemap.py b/forum/modules/template_loader.py/forum/sitemap.py
new file mode 100644 (file)
index 0000000..edb3220
--- /dev/null
@@ -0,0 +1,80 @@
+from django.contrib.sitemaps import Sitemap
+from forum.models import Question
+from django.conf import settings
+from django.http import HttpResponse, Http404
+from django.template import loader
+from django.core import urlresolvers
+from django.utils.encoding import smart_str
+from django.core.paginator import EmptyPage, PageNotAnInteger
+
+def index(request, sitemaps):
+    sites = []
+    for section, site in sitemaps.items():
+        if callable(site):
+            pages = site().paginator.num_pages
+        else:
+            pages = site.paginator.num_pages
+        sitemap_url = urlresolvers.reverse('forum.sitemap.sitemap', kwargs={'section': section})
+        sites.append('%s%s' % (settings.APP_URL, sitemap_url))
+        if pages > 1:
+            for page in range(2, pages+1):
+                sites.append('%s%s?p=%s' % (settings.APP_URL, sitemap_url, page))
+    xml = loader.render_to_string('sitemap_index.xml', {'sitemaps': sites})
+    return HttpResponse(xml, mimetype='application/xml')
+
+def sitemap(request, sitemaps, section=None):
+    maps, urls = [], []
+    if section is not None:
+        if section not in sitemaps:
+            raise Http404("No sitemap available for section: %r" % section)
+        maps.append(sitemaps[section])
+    else:
+        maps = sitemaps.values()
+    page = request.GET.get("p", 1)
+    
+    for site in maps:
+        try:
+            if callable(site):
+                urls.extend(site().get_urls(page=page))
+            else:
+                urls.extend(site.get_urls(page=page))
+        except EmptyPage:
+            raise Http404("Page %s empty" % page)
+        except PageNotAnInteger:
+            raise Http404("No page '%s'" % page)
+    xml = smart_str(loader.render_to_string('sitemap.xml', {'urlset': urls}))
+    return HttpResponse(xml, mimetype='application/xml')
+
+class OsqaSitemap(Sitemap):
+    changefreq = 'daily'
+    priority = 0.5
+    def items(self):
+        return Question.objects.filter_state(deleted=False)
+
+    def lastmod(self, obj):
+        return obj.last_activity_at
+
+    def location(self, obj):
+        return obj.get_absolute_url()
+
+    def __get(self, name, obj, default=None):
+        try:
+            attr = getattr(self, name)
+        except AttributeError:
+            return default
+        if callable(attr):
+            return attr(obj)
+        return attr
+
+    def get_urls(self, page=1):
+        urls = []
+        for item in self.paginator.page(page).object_list:
+            loc = "%s%s" % (settings.APP_URL, self.__get('location', item))
+            url_info = {
+                'location':   loc,
+                'lastmod':    self.__get('lastmod', item, None),
+                'changefreq': self.__get('changefreq', item, None),
+                'priority':   self.__get('priority', item, None)
+            }
+            urls.append(url_info)
+        return urls    
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/README b/forum/modules/template_loader.py/forum/skins/README
new file mode 100644 (file)
index 0000000..5565fa8
--- /dev/null
@@ -0,0 +1,22 @@
+this directory contains available skins
+
+1) default - default skin with templates
+2) common - this directory is to media directory common to all or many templates
+
+to create a new skin just create another directory under skins/
+and start populating it with the directory structure as in
+default/templates - templates must be named the same way
+
+NO NEED TO CREATE ALL TEMPLATES/MEDIA FILES AT ONCE
+
+templates are resolved in the following way:
+* check in skin named as in settings.OSQA_DEFAULT_SKIN
+* then skin named 'default'
+
+media is resolved with one extra option
+* settings.OSQA_DEFAULT_SKIN
+* 'default'
+* 'common'
+
+media does not have to be composed of files named the same way as in default skin
+whatever media you link to from your templates - will be in operation
diff --git a/forum/modules/template_loader.py/forum/skins/__init__.py b/forum/modules/template_loader.py/forum/skins/__init__.py
new file mode 100644 (file)
index 0000000..365ed9f
--- /dev/null
@@ -0,0 +1,144 @@
+from django.conf import settings
+from django.template.loaders import filesystem
+from django.template import TemplateDoesNotExist, Template as DJTemplate
+from django.conf import settings as djsettings
+import os.path
+import logging
+
+UNEXISTENT_TEMPLATE = object()
+
+SKINS_FOLDER = os.path.dirname(__file__)
+SKIN_TEMPLATES_FOLDER = 'templates'
+DEFAULT_SKIN_NAME = 'default'
+
+
+class Template(object):
+
+    def __init__(self, file_name):
+        self._file_name = file_name
+        self._loaded = False
+
+    def _get_mtime(self):
+        return os.path.getmtime(self._file_name)
+
+    def _check_mtime(self):
+        if self._last_mtime is None:
+            return False
+
+        return self._last_mtime == self._get_mtime()
+
+    def _load(self):
+        try:
+            f = open(self._file_name, 'r')
+            self._source = DJTemplate(f.read())
+            f.close()
+            self._loaded = True
+
+            self._last_mtime = self._get_mtime()
+        except:
+            self._loaded = False
+            self._last_mtime = None
+
+            raise
+
+    def return_tuple(self):
+        if not (self._loaded and self._check_mtime()):
+            try:
+                self._load()
+            except:
+                raise TemplateDoesNotExist, self._file_name
+
+        return self._source, self._file_name
+
+class BaseTemplateLoader(object):
+    is_usable = True
+
+    def __init__(self):
+        self.cache = {}
+
+    def __call__(self, name=None, dirs=None):
+        if name is None:
+            return self
+
+        return self.load_template(name, dirs)
+
+    def load_template(self, name, dirs=None):
+        if not djsettings.TEMPLATE_DEBUG:
+            if name in self.cache:
+                if self.cache[name] is UNEXISTENT_TEMPLATE:
+                    raise TemplateDoesNotExist, name
+
+                try:
+                    return self.cache[name].return_tuple()
+                except:
+                    del self.cache[name]
+
+        template = self.load_template_source(name, dirs)
+
+        if template is not None:
+            if not djsettings.DEBUG:
+                self.cache[name] = template
+
+            return template.return_tuple()
+        else:
+            if not djsettings.DEBUG:
+                self.cache[name] = UNEXISTENT_TEMPLATE
+
+            raise TemplateDoesNotExist, name
+
+    def load_template_source(self, name, dirs=None):
+        raise NotImplementedError
+
+
+class SkinsTemplateLoader(BaseTemplateLoader):
+
+    def load_template_source(self, name, dirs=None):
+        file_name = os.path.join(SKINS_FOLDER, settings.OSQA_DEFAULT_SKIN, SKIN_TEMPLATES_FOLDER, name)
+
+        if os.path.exists(file_name):
+            return Template(file_name)
+
+        file_name = os.path.join(SKINS_FOLDER, DEFAULT_SKIN_NAME, SKIN_TEMPLATES_FOLDER, name)
+
+        if os.path.exists(file_name):
+            return Template(file_name)
+
+        return None
+
+load_template_source = SkinsTemplateLoader()
+
+
+def find_media_source(url):
+    """returns url prefixed with the skin name
+    of the first skin that contains the file 
+    directories are searched in this order:
+    settings.OSQA_DEFAULT_SKIN, then 'default', then 'commmon'
+    if file is not found - returns None
+    and logs an error message
+    """
+    while url[0] == '/': url = url[1:]
+    d = os.path.dirname
+    n = os.path.normpath
+    j = os.path.join
+    f = os.path.isfile
+    skins = n(j(d(d(__file__)),'skins'))
+    try:
+        media = os.path.join(skins, settings.OSQA_DEFAULT_SKIN, url)
+        assert(f(media))
+        use_skin = settings.OSQA_DEFAULT_SKIN
+    except:
+        try:
+            media = j(skins, 'default', url)
+            assert(f(media))
+            use_skin = 'default'
+        except:
+            media = j(skins, 'common', url)
+            try:
+                assert(f(media))
+                use_skin = 'common'
+            except:
+                logging.error('could not find media for %s' % url)
+                use_skin = ''
+                return None
+    return use_skin + '/' + url
+
diff --git a/forum/modules/template_loader.py/forum/skins/common/media/README b/forum/modules/template_loader.py/forum/skins/common/media/README
new file mode 100644 (file)
index 0000000..3376e75
--- /dev/null
@@ -0,0 +1 @@
+directory for media common to all or many templates
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/blue-up-arrow-h18px.png b/forum/modules/template_loader.py/forum/skins/default/media/images/blue-up-arrow-h18px.png
new file mode 100644 (file)
index 0000000..e1f29e8
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/blue-up-arrow-h18px.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/box-arrow.gif b/forum/modules/template_loader.py/forum/skins/default/media/images/box-arrow.gif
new file mode 100644 (file)
index 0000000..89dcf5b
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/box-arrow.gif differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/bullet_green.gif b/forum/modules/template_loader.py/forum/skins/default/media/images/bullet_green.gif
new file mode 100644 (file)
index 0000000..fa53091
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/bullet_green.gif differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/by-sa-88x31.png b/forum/modules/template_loader.py/forum/skins/default/media/images/by-sa-88x31.png
new file mode 100644 (file)
index 0000000..f0a944e
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/by-sa-88x31.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/cc-88x31.png b/forum/modules/template_loader.py/forum/skins/default/media/images/cc-88x31.png
new file mode 100644 (file)
index 0000000..0f2a0f1
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/cc-88x31.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/cc-wiki.png b/forum/modules/template_loader.py/forum/skins/default/media/images/cc-wiki.png
new file mode 100644 (file)
index 0000000..3e68053
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/cc-wiki.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/close-small-dark.png b/forum/modules/template_loader.py/forum/skins/default/media/images/close-small-dark.png
new file mode 100644 (file)
index 0000000..280c1fc
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/close-small-dark.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/close-small-hover.png b/forum/modules/template_loader.py/forum/skins/default/media/images/close-small-hover.png
new file mode 100644 (file)
index 0000000..7899aec
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/close-small-hover.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/close-small.png b/forum/modules/template_loader.py/forum/skins/default/media/images/close-small.png
new file mode 100644 (file)
index 0000000..5a99d31
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/close-small.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/comment-delete-hover.png b/forum/modules/template_loader.py/forum/skins/default/media/images/comment-delete-hover.png
new file mode 100644 (file)
index 0000000..e8c69f4
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/comment-delete-hover.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/comment-delete.png b/forum/modules/template_loader.py/forum/skins/default/media/images/comment-delete.png
new file mode 100644 (file)
index 0000000..e1c2d8a
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/comment-delete.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/comment-edit-hover.png b/forum/modules/template_loader.py/forum/skins/default/media/images/comment-edit-hover.png
new file mode 100644 (file)
index 0000000..8291c56
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/comment-edit-hover.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/comment-edit.png b/forum/modules/template_loader.py/forum/skins/default/media/images/comment-edit.png
new file mode 100644 (file)
index 0000000..bad5c47
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/comment-edit.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/comment-like-on.png b/forum/modules/template_loader.py/forum/skins/default/media/images/comment-like-on.png
new file mode 100644 (file)
index 0000000..c2e497e
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/comment-like-on.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/comment-like.png b/forum/modules/template_loader.py/forum/skins/default/media/images/comment-like.png
new file mode 100644 (file)
index 0000000..87a19b9
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/comment-like.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/convert-hover.png b/forum/modules/template_loader.py/forum/skins/default/media/images/convert-hover.png
new file mode 100644 (file)
index 0000000..9e973ef
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/convert-hover.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/convert-off.png b/forum/modules/template_loader.py/forum/skins/default/media/images/convert-off.png
new file mode 100644 (file)
index 0000000..a10dddd
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/convert-off.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/dash.gif b/forum/modules/template_loader.py/forum/skins/default/media/images/dash.gif
new file mode 100644 (file)
index 0000000..d1ddc50
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/dash.gif differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/djangomade124x25_grey.gif b/forum/modules/template_loader.py/forum/skins/default/media/images/djangomade124x25_grey.gif
new file mode 100644 (file)
index 0000000..d34bb31
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/djangomade124x25_grey.gif differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/dot-g.gif b/forum/modules/template_loader.py/forum/skins/default/media/images/dot-g.gif
new file mode 100644 (file)
index 0000000..5d6bb28
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/dot-g.gif differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/dot-list.gif b/forum/modules/template_loader.py/forum/skins/default/media/images/dot-list.gif
new file mode 100644 (file)
index 0000000..f6a6b86
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/dot-list.gif differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/edit.png b/forum/modules/template_loader.py/forum/skins/default/media/images/edit.png
new file mode 100644 (file)
index 0000000..dcb09be
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/edit.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/expander-arrow-hide.gif b/forum/modules/template_loader.py/forum/skins/default/media/images/expander-arrow-hide.gif
new file mode 100644 (file)
index 0000000..feb6a61
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/expander-arrow-hide.gif differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/expander-arrow-show.gif b/forum/modules/template_loader.py/forum/skins/default/media/images/expander-arrow-show.gif
new file mode 100644 (file)
index 0000000..6825c56
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/expander-arrow-show.gif differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/favicon.gif b/forum/modules/template_loader.py/forum/skins/default/media/images/favicon.gif
new file mode 100644 (file)
index 0000000..910c266
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/favicon.gif differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/favicon.ico b/forum/modules/template_loader.py/forum/skins/default/media/images/favicon.ico
new file mode 100644 (file)
index 0000000..35c9e14
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/favicon.ico differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/feed-icon-small.png b/forum/modules/template_loader.py/forum/skins/default/media/images/feed-icon-small.png
new file mode 100644 (file)
index 0000000..b3c949d
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/feed-icon-small.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/gray-up-arrow-h18px.png b/forum/modules/template_loader.py/forum/skins/default/media/images/gray-up-arrow-h18px.png
new file mode 100644 (file)
index 0000000..7876744
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/gray-up-arrow-h18px.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/grippie.png b/forum/modules/template_loader.py/forum/skins/default/media/images/grippie.png
new file mode 100644 (file)
index 0000000..6524d41
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/grippie.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/indicator.gif b/forum/modules/template_loader.py/forum/skins/default/media/images/indicator.gif
new file mode 100644 (file)
index 0000000..1c72ebb
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/indicator.gif differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/logo.gif b/forum/modules/template_loader.py/forum/skins/default/media/images/logo.gif
new file mode 100644 (file)
index 0000000..ab690de
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/logo.gif differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/logo.png b/forum/modules/template_loader.py/forum/skins/default/media/images/logo.png
new file mode 100644 (file)
index 0000000..6a250e3
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/logo.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/logo1.png b/forum/modules/template_loader.py/forum/skins/default/media/images/logo1.png
new file mode 100644 (file)
index 0000000..d79a627
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/logo1.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/logo2.png b/forum/modules/template_loader.py/forum/skins/default/media/images/logo2.png
new file mode 100644 (file)
index 0000000..bd3cccd
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/logo2.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/medala.gif b/forum/modules/template_loader.py/forum/skins/default/media/images/medala.gif
new file mode 100644 (file)
index 0000000..93dd1a3
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/medala.gif differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/medala_on.gif b/forum/modules/template_loader.py/forum/skins/default/media/images/medala_on.gif
new file mode 100644 (file)
index 0000000..a18f9e8
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/medala_on.gif differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/new.gif b/forum/modules/template_loader.py/forum/skins/default/media/images/new.gif
new file mode 100644 (file)
index 0000000..8a220b5
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/new.gif differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/nophoto.png b/forum/modules/template_loader.py/forum/skins/default/media/images/nophoto.png
new file mode 100644 (file)
index 0000000..2daf0ff
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/nophoto.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/openid.gif b/forum/modules/template_loader.py/forum/skins/default/media/images/openid.gif
new file mode 100644 (file)
index 0000000..8540e12
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/openid.gif differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/openid/aol.gif b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/aol.gif
new file mode 100644 (file)
index 0000000..92373d5
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/aol.gif differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/openid/aol.png b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/aol.png
new file mode 100644 (file)
index 0000000..e5a51a8
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/aol.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/openid/blogger.ico b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/blogger.ico
new file mode 100644 (file)
index 0000000..1b9730b
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/blogger.ico differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/openid/blogger.png b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/blogger.png
new file mode 100644 (file)
index 0000000..3c46818
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/blogger.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/openid/claimid.ico b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/claimid.ico
new file mode 100644 (file)
index 0000000..2b80f49
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/claimid.ico differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/openid/claimid.png b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/claimid.png
new file mode 100644 (file)
index 0000000..441c0ed
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/claimid.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/openid/facebook.gif b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/facebook.gif
new file mode 100644 (file)
index 0000000..9a32529
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/facebook.gif differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/openid/flickr.ico b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/flickr.ico
new file mode 100644 (file)
index 0000000..11f6e07
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/flickr.ico differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/openid/flickr.png b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/flickr.png
new file mode 100644 (file)
index 0000000..6c443e1
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/flickr.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/openid/google.gif b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/google.gif
new file mode 100644 (file)
index 0000000..be451e5
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/google.gif differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/openid/livejournal.ico b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/livejournal.ico
new file mode 100644 (file)
index 0000000..f3d21ec
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/livejournal.ico differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/openid/livejournal.png b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/livejournal.png
new file mode 100644 (file)
index 0000000..9f2f6dd
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/livejournal.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/openid/myopenid.ico b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/myopenid.ico
new file mode 100644 (file)
index 0000000..ceb06e6
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/myopenid.ico differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/openid/myopenid.png b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/myopenid.png
new file mode 100644 (file)
index 0000000..e5df78d
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/myopenid.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/openid/myopenid_big.png b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/myopenid_big.png
new file mode 100644 (file)
index 0000000..8c357cb
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/myopenid_big.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/openid/openid-inputicon.gif b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/openid-inputicon.gif
new file mode 100644 (file)
index 0000000..cde836c
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/openid-inputicon.gif differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/openid/openid.gif b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/openid.gif
new file mode 100644 (file)
index 0000000..c718b0e
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/openid.gif differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/openid/technorati.ico b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/technorati.ico
new file mode 100644 (file)
index 0000000..fa1083c
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/technorati.ico differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/openid/technorati.png b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/technorati.png
new file mode 100644 (file)
index 0000000..7216641
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/technorati.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/openid/twitter.png b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/twitter.png
new file mode 100644 (file)
index 0000000..6178f9c
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/twitter.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/openid/verisign.ico b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/verisign.ico
new file mode 100644 (file)
index 0000000..3953af9
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/verisign.ico differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/openid/verisign.png b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/verisign.png
new file mode 100644 (file)
index 0000000..bc5c5f3
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/verisign.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/openid/vidoop.ico b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/vidoop.ico
new file mode 100644 (file)
index 0000000..bbd9a0d
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/vidoop.ico differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/openid/wordpress.ico b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/wordpress.ico
new file mode 100644 (file)
index 0000000..31b7d2c
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/wordpress.ico differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/openid/wordpress.png b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/wordpress.png
new file mode 100644 (file)
index 0000000..f261705
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/wordpress.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/openid/yahoo.gif b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/yahoo.gif
new file mode 100644 (file)
index 0000000..1ebaa7f
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/openid/yahoo.gif differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/quest-bg.gif b/forum/modules/template_loader.py/forum/skins/default/media/images/quest-bg.gif
new file mode 100644 (file)
index 0000000..b754023
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/quest-bg.gif differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/user-sprite.png b/forum/modules/template_loader.py/forum/skins/default/media/images/user-sprite.png
new file mode 100644 (file)
index 0000000..f437351
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/user-sprite.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/vote-accepted-on.png b/forum/modules/template_loader.py/forum/skins/default/media/images/vote-accepted-on.png
new file mode 100644 (file)
index 0000000..2026f3b
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/vote-accepted-on.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/vote-accepted.png b/forum/modules/template_loader.py/forum/skins/default/media/images/vote-accepted.png
new file mode 100644 (file)
index 0000000..ecd1855
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/vote-accepted.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/vote-arrow-down-on.png b/forum/modules/template_loader.py/forum/skins/default/media/images/vote-arrow-down-on.png
new file mode 100644 (file)
index 0000000..048dbb4
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/vote-arrow-down-on.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/vote-arrow-down.png b/forum/modules/template_loader.py/forum/skins/default/media/images/vote-arrow-down.png
new file mode 100644 (file)
index 0000000..e4fdec0
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/vote-arrow-down.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/vote-arrow-up-on.png b/forum/modules/template_loader.py/forum/skins/default/media/images/vote-arrow-up-on.png
new file mode 100644 (file)
index 0000000..56ad0c2
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/vote-arrow-up-on.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/vote-arrow-up.png b/forum/modules/template_loader.py/forum/skins/default/media/images/vote-arrow-up.png
new file mode 100644 (file)
index 0000000..6e9a51c
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/vote-arrow-up.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/vote-favorite-off.png b/forum/modules/template_loader.py/forum/skins/default/media/images/vote-favorite-off.png
new file mode 100644 (file)
index 0000000..c1bef07
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/vote-favorite-off.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/vote-favorite-on.png b/forum/modules/template_loader.py/forum/skins/default/media/images/vote-favorite-on.png
new file mode 100644 (file)
index 0000000..1f9c14a
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/vote-favorite-on.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/webfaction.png b/forum/modules/template_loader.py/forum/skins/default/media/images/webfaction.png
new file mode 100644 (file)
index 0000000..7c19d6c
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/webfaction.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/images/wiki.png b/forum/modules/template_loader.py/forum/skins/default/media/images/wiki.png
new file mode 100644 (file)
index 0000000..a6be558
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/images/wiki.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/compress.bat b/forum/modules/template_loader.py/forum/skins/default/media/js/compress.bat
new file mode 100644 (file)
index 0000000..f6f2a4f
--- /dev/null
@@ -0,0 +1 @@
+java -jar yuicompressor-2.4.2.jar --type js  --charset utf-8 osqa.main.js -o osqa.main.min.js
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/effects.core.min.js b/forum/modules/template_loader.py/forum/skins/default/media/js/effects.core.min.js
new file mode 100644 (file)
index 0000000..0a1d6d4
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * jQuery UI Effects 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/
+ */
+jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(var f=0;f<h.length;f++){if(h[f]!==null){g.data("ec.storage."+h[f],g[0].style[h[f]])}}},restore:function(g,h){for(var f=0;f<h.length;f++){if(h[f]!==null){g.css(h[f],g.data("ec.storage."+h[f]))}}},setMode:function(f,g){if(g=="toggle"){g=f.is(":hidden")?"show":"hide"}return g},getBaseline:function(g,h){var i,f;switch(g[0]){case"top":i=0;break;case"middle":i=0.5;break;case"bottom":i=1;break;default:i=g[0]/h.height}switch(g[1]){case"left":f=0;break;case"center":f=0.5;break;case"right":f=1;break;default:f=g[1]/h.width}return{x:f,y:i}},createWrapper:function(f){if(f.parent().is(".ui-effects-wrapper")){return f.parent()}var g={width:f.outerWidth(true),height:f.outerHeight(true),"float":f.css("float")};f.wrap('<div class="ui-effects-wrapper" style="font-size:100%;background:transparent;border:none;margin:0;padding:0"></div>');var j=f.parent();if(f.css("position")=="static"){j.css({position:"relative"});f.css({position:"relative"})}else{var i=f.css("top");if(isNaN(parseInt(i,10))){i="auto"}var h=f.css("left");if(isNaN(parseInt(h,10))){h="auto"}j.css({position:f.css("position"),top:i,left:h,zIndex:f.css("z-index")}).show();f.css({position:"relative",top:0,left:0})}j.css(g);return j},removeWrapper:function(f){if(f.parent().is(".ui-effects-wrapper")){return f.parent().replaceWith(f)}return f},setTransition:function(g,i,f,h){h=h||{};d.each(i,function(k,j){unit=g.cssUnit(j);if(unit[0]>0){h[j]=unit[0]*f+unit[1]}});return h},animateClass:function(h,i,k,j){var f=(typeof k=="function"?k:(j?j:null));var g=(typeof k=="string"?k:null);return this.each(function(){var q={};var o=d(this);var p=o.attr("style")||"";if(typeof p=="object"){p=p.cssText}if(h.toggle){o.hasClass(h.toggle)?h.remove=h.toggle:h.add=h.toggle}var l=d.extend({},(document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle));if(h.add){o.addClass(h.add)}if(h.remove){o.removeClass(h.remove)}var m=d.extend({},(document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle));if(h.add){o.removeClass(h.add)}if(h.remove){o.addClass(h.remove)}for(var r in m){if(typeof m[r]!="function"&&m[r]&&r.indexOf("Moz")==-1&&r.indexOf("length")==-1&&m[r]!=l[r]&&(r.match(/color/i)||(!r.match(/color/i)&&!isNaN(parseInt(m[r],10))))&&(l.position!="static"||(l.position=="static"&&!r.match(/left|top|bottom|right/)))){q[r]=m[r]}}o.animate(q,i,g,function(){if(typeof d(this).attr("style")=="object"){d(this).attr("style")["cssText"]="";d(this).attr("style")["cssText"]=p}else{d(this).attr("style",p)}if(h.add){d(this).addClass(h.add)}if(h.remove){d(this).removeClass(h.remove)}if(f){f.apply(this,arguments)}})})}};function c(g,f){var i=g[1]&&g[1].constructor==Object?g[1]:{};if(f){i.mode=f}var h=g[1]&&g[1].constructor!=Object?g[1]:(i.duration?i.duration:g[2]);h=d.fx.off?0:typeof h==="number"?h:d.fx.speeds[h]||d.fx.speeds._default;var j=i.callback||(d.isFunction(g[1])&&g[1])||(d.isFunction(g[2])&&g[2])||(d.isFunction(g[3])&&g[3]);return[g[0],i,h,j]}d.fn.extend({_show:d.fn.show,_hide:d.fn.hide,__toggle:d.fn.toggle,_addClass:d.fn.addClass,_removeClass:d.fn.removeClass,_toggleClass:d.fn.toggleClass,effect:function(g,f,h,i){return d.effects[g]?d.effects[g].call(this,{method:g,options:f||{},duration:h,callback:i}):null},show:function(){if(!arguments[0]||(arguments[0].constructor==Number||(/(slow|normal|fast)/).test(arguments[0]))){return this._show.apply(this,arguments)}else{return this.effect.apply(this,c(arguments,"show"))}},hide:function(){if(!arguments[0]||(arguments[0].constructor==Number||(/(slow|normal|fast)/).test(arguments[0]))){return this._hide.apply(this,arguments)}else{return this.effect.apply(this,c(arguments,"hide"))}},toggle:function(){if(!arguments[0]||(arguments[0].constructor==Number||(/(slow|normal|fast)/).test(arguments[0]))||(d.isFunction(arguments[0])||typeof arguments[0]=="boolean")){return this.__toggle.apply(this,arguments)}else{return this.effect.apply(this,c(arguments,"toggle"))}},addClass:function(g,f,i,h){return f?d.effects.animateClass.apply(this,[{add:g},f,i,h]):this._addClass(g)},removeClass:function(g,f,i,h){return f?d.effects.animateClass.apply(this,[{remove:g},f,i,h]):this._removeClass(g)},toggleClass:function(g,f,i,h){return((typeof f!=="boolean")&&f)?d.effects.animateClass.apply(this,[{toggle:g},f,i,h]):this._toggleClass(g,f)},morph:function(f,h,g,j,i){return d.effects.animateClass.apply(this,[{add:h,remove:f},g,j,i])},switchClass:function(){return this.morph.apply(this,arguments)},cssUnit:function(f){var g=this.css(f),h=[];d.each(["em","px","%","pt"],function(j,k){if(g.indexOf(k)>0){h=[parseFloat(g),k]}});return h}});d.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor","color","outlineColor"],function(g,f){d.fx.step[f]=function(h){if(h.state==0){h.start=e(h.elem,f);h.end=b(h.end)}h.elem.style[f]="rgb("+[Math.max(Math.min(parseInt((h.pos*(h.end[0]-h.start[0]))+h.start[0],10),255),0),Math.max(Math.min(parseInt((h.pos*(h.end[1]-h.start[1]))+h.start[1],10),255),0),Math.max(Math.min(parseInt((h.pos*(h.end[2]-h.start[2]))+h.start[2],10),255),0)].join(",")+")"}});function b(g){var f;if(g&&g.constructor==Array&&g.length==3){return g}if(f=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(g)){return[parseInt(f[1],10),parseInt(f[2],10),parseInt(f[3],10)]}if(f=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(g)){return[parseFloat(f[1])*2.55,parseFloat(f[2])*2.55,parseFloat(f[3])*2.55]}if(f=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(g)){return[parseInt(f[1],16),parseInt(f[2],16),parseInt(f[3],16)]}if(f=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(g)){return[parseInt(f[1]+f[1],16),parseInt(f[2]+f[2],16),parseInt(f[3]+f[3],16)]}if(f=/rgba\(0, 0, 0, 0\)/.exec(g)){return a.transparent}return a[d.trim(g).toLowerCase()]}function e(h,f){var g;do{g=d.curCSS(h,f);if(g!=""&&g!="transparent"||d.nodeName(h,"body")){break}f="backgroundColor"}while(h=h.parentNode);return b(g)}var a={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]};d.easing.jswing=d.easing.swing;d.extend(d.easing,{def:"easeOutQuad",swing:function(g,h,f,j,i){return d.easing[d.easing.def](g,h,f,j,i)},easeInQuad:function(g,h,f,j,i){return j*(h/=i)*h+f},easeOutQuad:function(g,h,f,j,i){return -j*(h/=i)*(h-2)+f},easeInOutQuad:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h+f}return -j/2*((--h)*(h-2)-1)+f},easeInCubic:function(g,h,f,j,i){return j*(h/=i)*h*h+f},easeOutCubic:function(g,h,f,j,i){return j*((h=h/i-1)*h*h+1)+f},easeInOutCubic:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h*h+f}return j/2*((h-=2)*h*h+2)+f},easeInQuart:function(g,h,f,j,i){return j*(h/=i)*h*h*h+f},easeOutQuart:function(g,h,f,j,i){return -j*((h=h/i-1)*h*h*h-1)+f},easeInOutQuart:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h*h*h+f}return -j/2*((h-=2)*h*h*h-2)+f},easeInQuint:function(g,h,f,j,i){return j*(h/=i)*h*h*h*h+f},easeOutQuint:function(g,h,f,j,i){return j*((h=h/i-1)*h*h*h*h+1)+f},easeInOutQuint:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h*h*h*h+f}return j/2*((h-=2)*h*h*h*h+2)+f},easeInSine:function(g,h,f,j,i){return -j*Math.cos(h/i*(Math.PI/2))+j+f},easeOutSine:function(g,h,f,j,i){return j*Math.sin(h/i*(Math.PI/2))+f},easeInOutSine:function(g,h,f,j,i){return -j/2*(Math.cos(Math.PI*h/i)-1)+f},easeInExpo:function(g,h,f,j,i){return(h==0)?f:j*Math.pow(2,10*(h/i-1))+f},easeOutExpo:function(g,h,f,j,i){return(h==i)?f+j:j*(-Math.pow(2,-10*h/i)+1)+f},easeInOutExpo:function(g,h,f,j,i){if(h==0){return f}if(h==i){return f+j}if((h/=i/2)<1){return j/2*Math.pow(2,10*(h-1))+f}return j/2*(-Math.pow(2,-10*--h)+2)+f},easeInCirc:function(g,h,f,j,i){return -j*(Math.sqrt(1-(h/=i)*h)-1)+f},easeOutCirc:function(g,h,f,j,i){return j*Math.sqrt(1-(h=h/i-1)*h)+f},easeInOutCirc:function(g,h,f,j,i){if((h/=i/2)<1){return -j/2*(Math.sqrt(1-h*h)-1)+f}return j/2*(Math.sqrt(1-(h-=2)*h)+1)+f},easeInElastic:function(g,i,f,m,l){var j=1.70158;var k=0;var h=m;if(i==0){return f}if((i/=l)==1){return f+m}if(!k){k=l*0.3}if(h<Math.abs(m)){h=m;var j=k/4}else{var j=k/(2*Math.PI)*Math.asin(m/h)}return -(h*Math.pow(2,10*(i-=1))*Math.sin((i*l-j)*(2*Math.PI)/k))+f},easeOutElastic:function(g,i,f,m,l){var j=1.70158;var k=0;var h=m;if(i==0){return f}if((i/=l)==1){return f+m}if(!k){k=l*0.3}if(h<Math.abs(m)){h=m;var j=k/4}else{var j=k/(2*Math.PI)*Math.asin(m/h)}return h*Math.pow(2,-10*i)*Math.sin((i*l-j)*(2*Math.PI)/k)+m+f},easeInOutElastic:function(g,i,f,m,l){var j=1.70158;var k=0;var h=m;if(i==0){return f}if((i/=l/2)==2){return f+m}if(!k){k=l*(0.3*1.5)}if(h<Math.abs(m)){h=m;var j=k/4}else{var j=k/(2*Math.PI)*Math.asin(m/h)}if(i<1){return -0.5*(h*Math.pow(2,10*(i-=1))*Math.sin((i*l-j)*(2*Math.PI)/k))+f}return h*Math.pow(2,-10*(i-=1))*Math.sin((i*l-j)*(2*Math.PI)/k)*0.5+m+f},easeInBack:function(g,h,f,k,j,i){if(i==undefined){i=1.70158}return k*(h/=j)*h*((i+1)*h-i)+f},easeOutBack:function(g,h,f,k,j,i){if(i==undefined){i=1.70158}return k*((h=h/j-1)*h*((i+1)*h+i)+1)+f},easeInOutBack:function(g,h,f,k,j,i){if(i==undefined){i=1.70158}if((h/=j/2)<1){return k/2*(h*h*(((i*=(1.525))+1)*h-i))+f}return k/2*((h-=2)*h*(((i*=(1.525))+1)*h+i)+2)+f},easeInBounce:function(g,h,f,j,i){return j-d.easing.easeOutBounce(g,i-h,0,j,i)+f},easeOutBounce:function(g,h,f,j,i){if((h/=i)<(1/2.75)){return j*(7.5625*h*h)+f}else{if(h<(2/2.75)){return j*(7.5625*(h-=(1.5/2.75))*h+0.75)+f}else{if(h<(2.5/2.75)){return j*(7.5625*(h-=(2.25/2.75))*h+0.9375)+f}else{return j*(7.5625*(h-=(2.625/2.75))*h+0.984375)+f}}}},easeInOutBounce:function(g,h,f,j,i){if(h<i/2){return d.easing.easeInBounce(g,h*2,0,j,i)*0.5+f}return d.easing.easeOutBounce(g,h*2-i,0,j,i)*0.5+j*0.5+f}})})(jQuery);
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/excanvas.min.js b/forum/modules/template_loader.py/forum/skins/default/media/js/excanvas.min.js
new file mode 100644 (file)
index 0000000..12c74f7
--- /dev/null
@@ -0,0 +1 @@
+if(!document.createElement("canvas").getContext){(function(){var z=Math;var K=z.round;var J=z.sin;var U=z.cos;var b=z.abs;var k=z.sqrt;var D=10;var F=D/2;function T(){return this.context_||(this.context_=new W(this))}var O=Array.prototype.slice;function G(i,j,m){var Z=O.call(arguments,2);return function(){return i.apply(j,Z.concat(O.call(arguments)))}}function AD(Z){return String(Z).replace(/&/g,"&amp;").replace(/"/g,"&quot;")}function r(i){if(!i.namespaces.g_vml_){i.namespaces.add("g_vml_","urn:schemas-microsoft-com:vml","#default#VML")}if(!i.namespaces.g_o_){i.namespaces.add("g_o_","urn:schemas-microsoft-com:office:office","#default#VML")}if(!i.styleSheets.ex_canvas_){var Z=i.createStyleSheet();Z.owningElement.id="ex_canvas_";Z.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}"}}r(document);var E={init:function(Z){if(/MSIE/.test(navigator.userAgent)&&!window.opera){var i=Z||document;i.createElement("canvas");i.attachEvent("onreadystatechange",G(this.init_,this,i))}},init_:function(m){var j=m.getElementsByTagName("canvas");for(var Z=0;Z<j.length;Z++){this.initElement(j[Z])}},initElement:function(i){if(!i.getContext){i.getContext=T;r(i.ownerDocument);i.innerHTML="";i.attachEvent("onpropertychange",S);i.attachEvent("onresize",w);var Z=i.attributes;if(Z.width&&Z.width.specified){i.style.width=Z.width.nodeValue+"px"}else{i.width=i.clientWidth}if(Z.height&&Z.height.specified){i.style.height=Z.height.nodeValue+"px"}else{i.height=i.clientHeight}}return i}};function S(i){var Z=i.srcElement;switch(i.propertyName){case"width":Z.getContext().clearRect();Z.style.width=Z.attributes.width.nodeValue+"px";Z.firstChild.style.width=Z.clientWidth+"px";break;case"height":Z.getContext().clearRect();Z.style.height=Z.attributes.height.nodeValue+"px";Z.firstChild.style.height=Z.clientHeight+"px";break}}function w(i){var Z=i.srcElement;if(Z.firstChild){Z.firstChild.style.width=Z.clientWidth+"px";Z.firstChild.style.height=Z.clientHeight+"px"}}E.init();var I=[];for(var AC=0;AC<16;AC++){for(var AB=0;AB<16;AB++){I[AC*16+AB]=AC.toString(16)+AB.toString(16)}}function V(){return[[1,0,0],[0,1,0],[0,0,1]]}function d(m,j){var i=V();for(var Z=0;Z<3;Z++){for(var AF=0;AF<3;AF++){var p=0;for(var AE=0;AE<3;AE++){p+=m[Z][AE]*j[AE][AF]}i[Z][AF]=p}}return i}function Q(i,Z){Z.fillStyle=i.fillStyle;Z.lineCap=i.lineCap;Z.lineJoin=i.lineJoin;Z.lineWidth=i.lineWidth;Z.miterLimit=i.miterLimit;Z.shadowBlur=i.shadowBlur;Z.shadowColor=i.shadowColor;Z.shadowOffsetX=i.shadowOffsetX;Z.shadowOffsetY=i.shadowOffsetY;Z.strokeStyle=i.strokeStyle;Z.globalAlpha=i.globalAlpha;Z.font=i.font;Z.textAlign=i.textAlign;Z.textBaseline=i.textBaseline;Z.arcScaleX_=i.arcScaleX_;Z.arcScaleY_=i.arcScaleY_;Z.lineScale_=i.lineScale_}var B={aliceblue:"#F0F8FF",antiquewhite:"#FAEBD7",aquamarine:"#7FFFD4",azure:"#F0FFFF",beige:"#F5F5DC",bisque:"#FFE4C4",black:"#000000",blanchedalmond:"#FFEBCD",blueviolet:"#8A2BE2",brown:"#A52A2A",burlywood:"#DEB887",cadetblue:"#5F9EA0",chartreuse:"#7FFF00",chocolate:"#D2691E",coral:"#FF7F50",cornflowerblue:"#6495ED",cornsilk:"#FFF8DC",crimson:"#DC143C",cyan:"#00FFFF",darkblue:"#00008B",darkcyan:"#008B8B",darkgoldenrod:"#B8860B",darkgray:"#A9A9A9",darkgreen:"#006400",darkgrey:"#A9A9A9",darkkhaki:"#BDB76B",darkmagenta:"#8B008B",darkolivegreen:"#556B2F",darkorange:"#FF8C00",darkorchid:"#9932CC",darkred:"#8B0000",darksalmon:"#E9967A",darkseagreen:"#8FBC8F",darkslateblue:"#483D8B",darkslategray:"#2F4F4F",darkslategrey:"#2F4F4F",darkturquoise:"#00CED1",darkviolet:"#9400D3",deeppink:"#FF1493",deepskyblue:"#00BFFF",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1E90FF",firebrick:"#B22222",floralwhite:"#FFFAF0",forestgreen:"#228B22",gainsboro:"#DCDCDC",ghostwhite:"#F8F8FF",gold:"#FFD700",goldenrod:"#DAA520",grey:"#808080",greenyellow:"#ADFF2F",honeydew:"#F0FFF0",hotpink:"#FF69B4",indianred:"#CD5C5C",indigo:"#4B0082",ivory:"#FFFFF0",khaki:"#F0E68C",lavender:"#E6E6FA",lavenderblush:"#FFF0F5",lawngreen:"#7CFC00",lemonchiffon:"#FFFACD",lightblue:"#ADD8E6",lightcoral:"#F08080",lightcyan:"#E0FFFF",lightgoldenrodyellow:"#FAFAD2",lightgreen:"#90EE90",lightgrey:"#D3D3D3",lightpink:"#FFB6C1",lightsalmon:"#FFA07A",lightseagreen:"#20B2AA",lightskyblue:"#87CEFA",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#B0C4DE",lightyellow:"#FFFFE0",limegreen:"#32CD32",linen:"#FAF0E6",magenta:"#FF00FF",mediumaquamarine:"#66CDAA",mediumblue:"#0000CD",mediumorchid:"#BA55D3",mediumpurple:"#9370DB",mediumseagreen:"#3CB371",mediumslateblue:"#7B68EE",mediumspringgreen:"#00FA9A",mediumturquoise:"#48D1CC",mediumvioletred:"#C71585",midnightblue:"#191970",mintcream:"#F5FFFA",mistyrose:"#FFE4E1",moccasin:"#FFE4B5",navajowhite:"#FFDEAD",oldlace:"#FDF5E6",olivedrab:"#6B8E23",orange:"#FFA500",orangered:"#FF4500",orchid:"#DA70D6",palegoldenrod:"#EEE8AA",palegreen:"#98FB98",paleturquoise:"#AFEEEE",palevioletred:"#DB7093",papayawhip:"#FFEFD5",peachpuff:"#FFDAB9",peru:"#CD853F",pink:"#FFC0CB",plum:"#DDA0DD",powderblue:"#B0E0E6",rosybrown:"#BC8F8F",royalblue:"#4169E1",saddlebrown:"#8B4513",salmon:"#FA8072",sandybrown:"#F4A460",seagreen:"#2E8B57",seashell:"#FFF5EE",sienna:"#A0522D",skyblue:"#87CEEB",slateblue:"#6A5ACD",slategray:"#708090",slategrey:"#708090",snow:"#FFFAFA",springgreen:"#00FF7F",steelblue:"#4682B4",tan:"#D2B48C",thistle:"#D8BFD8",tomato:"#FF6347",turquoise:"#40E0D0",violet:"#EE82EE",wheat:"#F5DEB3",whitesmoke:"#F5F5F5",yellowgreen:"#9ACD32"};function g(i){var m=i.indexOf("(",3);var Z=i.indexOf(")",m+1);var j=i.substring(m+1,Z).split(",");if(j.length==4&&i.substr(3,1)=="a"){alpha=Number(j[3])}else{j[3]=1}return j}function C(Z){return parseFloat(Z)/100}function N(i,j,Z){return Math.min(Z,Math.max(j,i))}function c(AF){var j,i,Z;h=parseFloat(AF[0])/360%360;if(h<0){h++}s=N(C(AF[1]),0,1);l=N(C(AF[2]),0,1);if(s==0){j=i=Z=l}else{var m=l<0.5?l*(1+s):l+s-l*s;var AE=2*l-m;j=A(AE,m,h+1/3);i=A(AE,m,h);Z=A(AE,m,h-1/3)}return"#"+I[Math.floor(j*255)]+I[Math.floor(i*255)]+I[Math.floor(Z*255)]}function A(i,Z,j){if(j<0){j++}if(j>1){j--}if(6*j<1){return i+(Z-i)*6*j}else{if(2*j<1){return Z}else{if(3*j<2){return i+(Z-i)*(2/3-j)*6}else{return i}}}}function Y(Z){var AE,p=1;Z=String(Z);if(Z.charAt(0)=="#"){AE=Z}else{if(/^rgb/.test(Z)){var m=g(Z);var AE="#",AF;for(var j=0;j<3;j++){if(m[j].indexOf("%")!=-1){AF=Math.floor(C(m[j])*255)}else{AF=Number(m[j])}AE+=I[N(AF,0,255)]}p=m[3]}else{if(/^hsl/.test(Z)){var m=g(Z);AE=c(m);p=m[3]}else{AE=B[Z]||Z}}}return{color:AE,alpha:p}}var L={style:"normal",variant:"normal",weight:"normal",size:10,family:"sans-serif"};var f={};function X(Z){if(f[Z]){return f[Z]}var m=document.createElement("div");var j=m.style;try{j.font=Z}catch(i){}return f[Z]={style:j.fontStyle||L.style,variant:j.fontVariant||L.variant,weight:j.fontWeight||L.weight,size:j.fontSize||L.size,family:j.fontFamily||L.family}}function P(j,i){var Z={};for(var AF in j){Z[AF]=j[AF]}var AE=parseFloat(i.currentStyle.fontSize),m=parseFloat(j.size);if(typeof j.size=="number"){Z.size=j.size}else{if(j.size.indexOf("px")!=-1){Z.size=m}else{if(j.size.indexOf("em")!=-1){Z.size=AE*m}else{if(j.size.indexOf("%")!=-1){Z.size=(AE/100)*m}else{if(j.size.indexOf("pt")!=-1){Z.size=m/0.75}else{Z.size=AE}}}}}Z.size*=0.981;return Z}function AA(Z){return Z.style+" "+Z.variant+" "+Z.weight+" "+Z.size+"px "+Z.family}function t(Z){switch(Z){case"butt":return"flat";case"round":return"round";case"square":default:return"square"}}function W(i){this.m_=V();this.mStack_=[];this.aStack_=[];this.currentPath_=[];this.strokeStyle="#000";this.fillStyle="#000";this.lineWidth=1;this.lineJoin="miter";this.lineCap="butt";this.miterLimit=D*1;this.globalAlpha=1;this.font="10px sans-serif";this.textAlign="left";this.textBaseline="alphabetic";this.canvas=i;var Z=i.ownerDocument.createElement("div");Z.style.width=i.clientWidth+"px";Z.style.height=i.clientHeight+"px";Z.style.overflow="hidden";Z.style.position="absolute";i.appendChild(Z);this.element_=Z;this.arcScaleX_=1;this.arcScaleY_=1;this.lineScale_=1}var M=W.prototype;M.clearRect=function(){if(this.textMeasureEl_){this.textMeasureEl_.removeNode(true);this.textMeasureEl_=null}this.element_.innerHTML=""};M.beginPath=function(){this.currentPath_=[]};M.moveTo=function(i,Z){var j=this.getCoords_(i,Z);this.currentPath_.push({type:"moveTo",x:j.x,y:j.y});this.currentX_=j.x;this.currentY_=j.y};M.lineTo=function(i,Z){var j=this.getCoords_(i,Z);this.currentPath_.push({type:"lineTo",x:j.x,y:j.y});this.currentX_=j.x;this.currentY_=j.y};M.bezierCurveTo=function(j,i,AI,AH,AG,AE){var Z=this.getCoords_(AG,AE);var AF=this.getCoords_(j,i);var m=this.getCoords_(AI,AH);e(this,AF,m,Z)};function e(Z,m,j,i){Z.currentPath_.push({type:"bezierCurveTo",cp1x:m.x,cp1y:m.y,cp2x:j.x,cp2y:j.y,x:i.x,y:i.y});Z.currentX_=i.x;Z.currentY_=i.y}M.quadraticCurveTo=function(AG,j,i,Z){var AF=this.getCoords_(AG,j);var AE=this.getCoords_(i,Z);var AH={x:this.currentX_+2/3*(AF.x-this.currentX_),y:this.currentY_+2/3*(AF.y-this.currentY_)};var m={x:AH.x+(AE.x-this.currentX_)/3,y:AH.y+(AE.y-this.currentY_)/3};e(this,AH,m,AE)};M.arc=function(AJ,AH,AI,AE,i,j){AI*=D;var AN=j?"at":"wa";var AK=AJ+U(AE)*AI-F;var AM=AH+J(AE)*AI-F;var Z=AJ+U(i)*AI-F;var AL=AH+J(i)*AI-F;if(AK==Z&&!j){AK+=0.125}var m=this.getCoords_(AJ,AH);var AG=this.getCoords_(AK,AM);var AF=this.getCoords_(Z,AL);this.currentPath_.push({type:AN,x:m.x,y:m.y,radius:AI,xStart:AG.x,yStart:AG.y,xEnd:AF.x,yEnd:AF.y})};M.rect=function(j,i,Z,m){this.moveTo(j,i);this.lineTo(j+Z,i);this.lineTo(j+Z,i+m);this.lineTo(j,i+m);this.closePath()};M.strokeRect=function(j,i,Z,m){var p=this.currentPath_;this.beginPath();this.moveTo(j,i);this.lineTo(j+Z,i);this.lineTo(j+Z,i+m);this.lineTo(j,i+m);this.closePath();this.stroke();this.currentPath_=p};M.fillRect=function(j,i,Z,m){var p=this.currentPath_;this.beginPath();this.moveTo(j,i);this.lineTo(j+Z,i);this.lineTo(j+Z,i+m);this.lineTo(j,i+m);this.closePath();this.fill();this.currentPath_=p};M.createLinearGradient=function(i,m,Z,j){var p=new v("gradient");p.x0_=i;p.y0_=m;p.x1_=Z;p.y1_=j;return p};M.createRadialGradient=function(m,AE,j,i,p,Z){var AF=new v("gradientradial");AF.x0_=m;AF.y0_=AE;AF.r0_=j;AF.x1_=i;AF.y1_=p;AF.r1_=Z;return AF};M.drawImage=function(AO,j){var AH,AF,AJ,AV,AM,AK,AQ,AX;var AI=AO.runtimeStyle.width;var AN=AO.runtimeStyle.height;AO.runtimeStyle.width="auto";AO.runtimeStyle.height="auto";var AG=AO.width;var AT=AO.height;AO.runtimeStyle.width=AI;AO.runtimeStyle.height=AN;if(arguments.length==3){AH=arguments[1];AF=arguments[2];AM=AK=0;AQ=AJ=AG;AX=AV=AT}else{if(arguments.length==5){AH=arguments[1];AF=arguments[2];AJ=arguments[3];AV=arguments[4];AM=AK=0;AQ=AG;AX=AT}else{if(arguments.length==9){AM=arguments[1];AK=arguments[2];AQ=arguments[3];AX=arguments[4];AH=arguments[5];AF=arguments[6];AJ=arguments[7];AV=arguments[8]}else{throw Error("Invalid number of arguments")}}}var AW=this.getCoords_(AH,AF);var m=AQ/2;var i=AX/2;var AU=[];var Z=10;var AE=10;AU.push(" <g_vml_:group",' coordsize="',D*Z,",",D*AE,'"',' coordorigin="0,0"',' style="width:',Z,"px;height:",AE,"px;position:absolute;");if(this.m_[0][0]!=1||this.m_[0][1]||this.m_[1][1]!=1||this.m_[1][0]){var p=[];p.push("M11=",this.m_[0][0],",","M12=",this.m_[1][0],",","M21=",this.m_[0][1],",","M22=",this.m_[1][1],",","Dx=",K(AW.x/D),",","Dy=",K(AW.y/D),"");var AS=AW;var AR=this.getCoords_(AH+AJ,AF);var AP=this.getCoords_(AH,AF+AV);var AL=this.getCoords_(AH+AJ,AF+AV);AS.x=z.max(AS.x,AR.x,AP.x,AL.x);AS.y=z.max(AS.y,AR.y,AP.y,AL.y);AU.push("padding:0 ",K(AS.x/D),"px ",K(AS.y/D),"px 0;filter:progid:DXImageTransform.Microsoft.Matrix(",p.join(""),", sizingmethod='clip');")}else{AU.push("top:",K(AW.y/D),"px;left:",K(AW.x/D),"px;")}AU.push(' ">','<g_vml_:image src="',AO.src,'"',' style="width:',D*AJ,"px;"," height:",D*AV,'px"',' cropleft="',AM/AG,'"',' croptop="',AK/AT,'"',' cropright="',(AG-AM-AQ)/AG,'"',' cropbottom="',(AT-AK-AX)/AT,'"'," />","</g_vml_:group>");this.element_.insertAdjacentHTML("BeforeEnd",AU.join(""))};M.stroke=function(AM){var m=10;var AN=10;var AE=5000;var AG={x:null,y:null};var AL={x:null,y:null};for(var AH=0;AH<this.currentPath_.length;AH+=AE){var AK=[];var AF=false;AK.push("<g_vml_:shape",' filled="',!!AM,'"',' style="position:absolute;width:',m,"px;height:",AN,'px;"',' coordorigin="0,0"',' coordsize="',D*m,",",D*AN,'"',' stroked="',!AM,'"',' path="');var AO=false;for(var AI=AH;AI<Math.min(AH+AE,this.currentPath_.length);AI++){if(AI%AE==0&&AI>0){AK.push(" m ",K(this.currentPath_[AI-1].x),",",K(this.currentPath_[AI-1].y))}var Z=this.currentPath_[AI];var AJ;switch(Z.type){case"moveTo":AJ=Z;AK.push(" m ",K(Z.x),",",K(Z.y));break;case"lineTo":AK.push(" l ",K(Z.x),",",K(Z.y));break;case"close":AK.push(" x ");Z=null;break;case"bezierCurveTo":AK.push(" c ",K(Z.cp1x),",",K(Z.cp1y),",",K(Z.cp2x),",",K(Z.cp2y),",",K(Z.x),",",K(Z.y));break;case"at":case"wa":AK.push(" ",Z.type," ",K(Z.x-this.arcScaleX_*Z.radius),",",K(Z.y-this.arcScaleY_*Z.radius)," ",K(Z.x+this.arcScaleX_*Z.radius),",",K(Z.y+this.arcScaleY_*Z.radius)," ",K(Z.xStart),",",K(Z.yStart)," ",K(Z.xEnd),",",K(Z.yEnd));break}if(Z){if(AG.x==null||Z.x<AG.x){AG.x=Z.x}if(AL.x==null||Z.x>AL.x){AL.x=Z.x}if(AG.y==null||Z.y<AG.y){AG.y=Z.y}if(AL.y==null||Z.y>AL.y){AL.y=Z.y}}}AK.push(' ">');if(!AM){R(this,AK)}else{a(this,AK,AG,AL)}AK.push("</g_vml_:shape>");this.element_.insertAdjacentHTML("beforeEnd",AK.join(""))}};function R(j,AE){var i=Y(j.strokeStyle);var m=i.color;var p=i.alpha*j.globalAlpha;var Z=j.lineScale_*j.lineWidth;if(Z<1){p*=Z}AE.push("<g_vml_:stroke",' opacity="',p,'"',' joinstyle="',j.lineJoin,'"',' miterlimit="',j.miterLimit,'"',' endcap="',t(j.lineCap),'"',' weight="',Z,'px"',' color="',m,'" />')}function a(AO,AG,Ah,AP){var AH=AO.fillStyle;var AY=AO.arcScaleX_;var AX=AO.arcScaleY_;var Z=AP.x-Ah.x;var m=AP.y-Ah.y;if(AH instanceof v){var AL=0;var Ac={x:0,y:0};var AU=0;var AK=1;if(AH.type_=="gradient"){var AJ=AH.x0_/AY;var j=AH.y0_/AX;var AI=AH.x1_/AY;var Aj=AH.y1_/AX;var Ag=AO.getCoords_(AJ,j);var Af=AO.getCoords_(AI,Aj);var AE=Af.x-Ag.x;var p=Af.y-Ag.y;AL=Math.atan2(AE,p)*180/Math.PI;if(AL<0){AL+=360}if(AL<0.000001){AL=0}}else{var Ag=AO.getCoords_(AH.x0_,AH.y0_);Ac={x:(Ag.x-Ah.x)/Z,y:(Ag.y-Ah.y)/m};Z/=AY*D;m/=AX*D;var Aa=z.max(Z,m);AU=2*AH.r0_/Aa;AK=2*AH.r1_/Aa-AU}var AS=AH.colors_;AS.sort(function(Ak,i){return Ak.offset-i.offset});var AN=AS.length;var AR=AS[0].color;var AQ=AS[AN-1].color;var AW=AS[0].alpha*AO.globalAlpha;var AV=AS[AN-1].alpha*AO.globalAlpha;var Ab=[];for(var Ae=0;Ae<AN;Ae++){var AM=AS[Ae];Ab.push(AM.offset*AK+AU+" "+AM.color)}AG.push('<g_vml_:fill type="',AH.type_,'"',' method="none" focus="100%"',' color="',AR,'"',' color2="',AQ,'"',' colors="',Ab.join(","),'"',' opacity="',AV,'"',' g_o_:opacity2="',AW,'"',' angle="',AL,'"',' focusposition="',Ac.x,",",Ac.y,'" />')}else{if(AH instanceof u){if(Z&&m){var AF=-Ah.x;var AZ=-Ah.y;AG.push("<g_vml_:fill",' position="',AF/Z*AY*AY,",",AZ/m*AX*AX,'"',' type="tile"',' src="',AH.src_,'" />')}}else{var Ai=Y(AO.fillStyle);var AT=Ai.color;var Ad=Ai.alpha*AO.globalAlpha;AG.push('<g_vml_:fill color="',AT,'" opacity="',Ad,'" />')}}}M.fill=function(){this.stroke(true)};M.closePath=function(){this.currentPath_.push({type:"close"})};M.getCoords_=function(j,i){var Z=this.m_;return{x:D*(j*Z[0][0]+i*Z[1][0]+Z[2][0])-F,y:D*(j*Z[0][1]+i*Z[1][1]+Z[2][1])-F}};M.save=function(){var Z={};Q(this,Z);this.aStack_.push(Z);this.mStack_.push(this.m_);this.m_=d(V(),this.m_)};M.restore=function(){if(this.aStack_.length){Q(this.aStack_.pop(),this);this.m_=this.mStack_.pop()}};function H(Z){return isFinite(Z[0][0])&&isFinite(Z[0][1])&&isFinite(Z[1][0])&&isFinite(Z[1][1])&&isFinite(Z[2][0])&&isFinite(Z[2][1])}function y(i,Z,j){if(!H(Z)){return }i.m_=Z;if(j){var p=Z[0][0]*Z[1][1]-Z[0][1]*Z[1][0];i.lineScale_=k(b(p))}}M.translate=function(j,i){var Z=[[1,0,0],[0,1,0],[j,i,1]];y(this,d(Z,this.m_),false)};M.rotate=function(i){var m=U(i);var j=J(i);var Z=[[m,j,0],[-j,m,0],[0,0,1]];y(this,d(Z,this.m_),false)};M.scale=function(j,i){this.arcScaleX_*=j;this.arcScaleY_*=i;var Z=[[j,0,0],[0,i,0],[0,0,1]];y(this,d(Z,this.m_),true)};M.transform=function(p,m,AF,AE,i,Z){var j=[[p,m,0],[AF,AE,0],[i,Z,1]];y(this,d(j,this.m_),true)};M.setTransform=function(AE,p,AG,AF,j,i){var Z=[[AE,p,0],[AG,AF,0],[j,i,1]];y(this,Z,true)};M.drawText_=function(AK,AI,AH,AN,AG){var AM=this.m_,AQ=1000,i=0,AP=AQ,AF={x:0,y:0},AE=[];var Z=P(X(this.font),this.element_);var j=AA(Z);var AR=this.element_.currentStyle;var p=this.textAlign.toLowerCase();switch(p){case"left":case"center":case"right":break;case"end":p=AR.direction=="ltr"?"right":"left";break;case"start":p=AR.direction=="rtl"?"right":"left";break;default:p="left"}switch(this.textBaseline){case"hanging":case"top":AF.y=Z.size/1.75;break;case"middle":break;default:case null:case"alphabetic":case"ideographic":case"bottom":AF.y=-Z.size/2.25;break}switch(p){case"right":i=AQ;AP=0.05;break;case"center":i=AP=AQ/2;break}var AO=this.getCoords_(AI+AF.x,AH+AF.y);AE.push('<g_vml_:line from="',-i,' 0" to="',AP,' 0.05" ',' coordsize="100 100" coordorigin="0 0"',' filled="',!AG,'" stroked="',!!AG,'" style="position:absolute;width:1px;height:1px;">');if(AG){R(this,AE)}else{a(this,AE,{x:-i,y:0},{x:AP,y:Z.size})}var AL=AM[0][0].toFixed(3)+","+AM[1][0].toFixed(3)+","+AM[0][1].toFixed(3)+","+AM[1][1].toFixed(3)+",0,0";var AJ=K(AO.x/D)+","+K(AO.y/D);AE.push('<g_vml_:skew on="t" matrix="',AL,'" ',' offset="',AJ,'" origin="',i,' 0" />','<g_vml_:path textpathok="true" />','<g_vml_:textpath on="true" string="',AD(AK),'" style="v-text-align:',p,";font:",AD(j),'" /></g_vml_:line>');this.element_.insertAdjacentHTML("beforeEnd",AE.join(""))};M.fillText=function(j,Z,m,i){this.drawText_(j,Z,m,i,false)};M.strokeText=function(j,Z,m,i){this.drawText_(j,Z,m,i,true)};M.measureText=function(j){if(!this.textMeasureEl_){var Z='<span style="position:absolute;top:-20000px;left:0;padding:0;margin:0;border:none;white-space:pre;"></span>';this.element_.insertAdjacentHTML("beforeEnd",Z);this.textMeasureEl_=this.element_.lastChild}var i=this.element_.ownerDocument;this.textMeasureEl_.innerHTML="";this.textMeasureEl_.style.font=this.font;this.textMeasureEl_.appendChild(i.createTextNode(j));return{width:this.textMeasureEl_.offsetWidth}};M.clip=function(){};M.arcTo=function(){};M.createPattern=function(i,Z){return new u(i,Z)};function v(Z){this.type_=Z;this.x0_=0;this.y0_=0;this.r0_=0;this.x1_=0;this.y1_=0;this.r1_=0;this.colors_=[]}v.prototype.addColorStop=function(i,Z){Z=Y(Z);this.colors_.push({offset:i,color:Z.color,alpha:Z.alpha})};function u(i,Z){q(i);switch(Z){case"repeat":case null:case"":this.repetition_="repeat";break;case"repeat-x":case"repeat-y":case"no-repeat":this.repetition_=Z;break;default:n("SYNTAX_ERR")}this.src_=i.src;this.width_=i.width;this.height_=i.height}function n(Z){throw new o(Z)}function q(Z){if(!Z||Z.nodeType!=1||Z.tagName!="IMG"){n("TYPE_MISMATCH_ERR")}if(Z.readyState!="complete"){n("INVALID_STATE_ERR")}}function o(Z){this.code=this[Z];this.message=Z+": DOM Exception "+this.code}var x=o.prototype=new Error;x.INDEX_SIZE_ERR=1;x.DOMSTRING_SIZE_ERR=2;x.HIERARCHY_REQUEST_ERR=3;x.WRONG_DOCUMENT_ERR=4;x.INVALID_CHARACTER_ERR=5;x.NO_DATA_ALLOWED_ERR=6;x.NO_MODIFICATION_ALLOWED_ERR=7;x.NOT_FOUND_ERR=8;x.NOT_SUPPORTED_ERR=9;x.INUSE_ATTRIBUTE_ERR=10;x.INVALID_STATE_ERR=11;x.SYNTAX_ERR=12;x.INVALID_MODIFICATION_ERR=13;x.NAMESPACE_ERR=14;x.INVALID_ACCESS_ERR=15;x.VALIDATION_ERR=16;x.TYPE_MISMATCH_ERR=17;G_vmlCanvasManager=E;CanvasRenderingContext2D=W;CanvasGradient=v;CanvasPattern=u;DOMException=o})()};
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/flot-build.bat b/forum/modules/template_loader.py/forum/skins/default/media/js/flot-build.bat
new file mode 100644 (file)
index 0000000..f9f32cb
--- /dev/null
@@ -0,0 +1,3 @@
+java -jar yuicompressor-2.4.2.jar --type js  --charset utf-8 jquery.flot.js -o jquery.flot.pack.js
+
+pause
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/jquery-1.2.6.js b/forum/modules/template_loader.py/forum/skins/default/media/js/jquery-1.2.6.js
new file mode 100644 (file)
index 0000000..88e661e
--- /dev/null
@@ -0,0 +1,3549 @@
+(function(){
+/*
+ * jQuery 1.2.6 - New Wave Javascript
+ *
+ * Copyright (c) 2008 John Resig (jquery.com)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * $Date: 2008-05-24 14:22:17 -0400 (Sat, 24 May 2008) $
+ * $Rev: 5685 $
+ */
+
+// Map over jQuery in case of overwrite
+var _jQuery = window.jQuery,
+// Map over the $ in case of overwrite
+       _$ = window.$;
+
+var jQuery = window.jQuery = window.$ = function( selector, context ) {
+       // The jQuery object is actually just the init constructor 'enhanced'
+       return new jQuery.fn.init( selector, context );
+};
+
+// A simple way to check for HTML strings or ID strings
+// (both of which we optimize for)
+var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/,
+
+// Is it a simple selector
+       isSimple = /^.[^:#\[\.]*$/,
+
+// Will speed up references to undefined, and allows munging its name.
+       undefined;
+
+jQuery.fn = jQuery.prototype = {
+       init: function( selector, context ) {
+               // Make sure that a selection was provided
+               selector = selector || document;
+
+               // Handle $(DOMElement)
+               if ( selector.nodeType ) {
+                       this[0] = selector;
+                       this.length = 1;
+                       return this;
+               }
+               // Handle HTML strings
+               if ( typeof selector == "string" ) {
+                       // Are we dealing with HTML string or an ID?
+                       var match = quickExpr.exec( selector );
+
+                       // Verify a match, and that no context was specified for #id
+                       if ( match && (match[1] || !context) ) {
+
+                               // HANDLE: $(html) -> $(array)
+                               if ( match[1] )
+                                       selector = jQuery.clean( [ match[1] ], context );
+
+                               // HANDLE: $("#id")
+                               else {
+                                       var elem = document.getElementById( match[3] );
+
+                                       // Make sure an element was located
+                                       if ( elem ){
+                                               // Handle the case where IE and Opera return items
+                                               // by name instead of ID
+                                               if ( elem.id != match[3] )
+                                                       return jQuery().find( selector );
+
+                                               // Otherwise, we inject the element directly into the jQuery object
+                                               return jQuery( elem );
+                                       }
+                                       selector = [];
+                               }
+
+                       // HANDLE: $(expr, [context])
+                       // (which is just equivalent to: $(content).find(expr)
+                       } else
+                               return jQuery( context ).find( selector );
+
+               // HANDLE: $(function)
+               // Shortcut for document ready
+               } else if ( jQuery.isFunction( selector ) )
+                       return jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector );
+
+               return this.setArray(jQuery.makeArray(selector));
+       },
+
+       // The current version of jQuery being used
+       jquery: "1.2.6",
+
+       // The number of elements contained in the matched element set
+       size: function() {
+               return this.length;
+       },
+
+       // The number of elements contained in the matched element set
+       length: 0,
+
+       // Get the Nth element in the matched element set OR
+       // Get the whole matched element set as a clean array
+       get: function( num ) {
+               return num == undefined ?
+
+                       // Return a 'clean' array
+                       jQuery.makeArray( this ) :
+
+                       // Return just the object
+                       this[ num ];
+       },
+
+       // Take an array of elements and push it onto the stack
+       // (returning the new matched element set)
+       pushStack: function( elems ) {
+               // Build a new jQuery matched element set
+               var ret = jQuery( elems );
+
+               // Add the old object onto the stack (as a reference)
+               ret.prevObject = this;
+
+               // Return the newly-formed element set
+               return ret;
+       },
+
+       // Force the current matched set of elements to become
+       // the specified array of elements (destroying the stack in the process)
+       // You should use pushStack() in order to do this, but maintain the stack
+       setArray: function( elems ) {
+               // Resetting the length to 0, then using the native Array push
+               // is a super-fast way to populate an object with array-like properties
+               this.length = 0;
+               Array.prototype.push.apply( this, elems );
+
+               return this;
+       },
+
+       // Execute a callback for every element in the matched set.
+       // (You can seed the arguments with an array of args, but this is
+       // only used internally.)
+       each: function( callback, args ) {
+               return jQuery.each( this, callback, args );
+       },
+
+       // Determine the position of an element within
+       // the matched set of elements
+       index: function( elem ) {
+               var ret = -1;
+
+               // Locate the position of the desired element
+               return jQuery.inArray(
+                       // If it receives a jQuery object, the first element is used
+                       elem && elem.jquery ? elem[0] : elem
+               , this );
+       },
+
+       attr: function( name, value, type ) {
+               var options = name;
+
+               // Look for the case where we're accessing a style value
+               if ( name.constructor == String )
+                       if ( value === undefined )
+                               return this[0] && jQuery[ type || "attr" ]( this[0], name );
+
+                       else {
+                               options = {};
+                               options[ name ] = value;
+                       }
+
+               // Check to see if we're setting style values
+               return this.each(function(i){
+                       // Set all the styles
+                       for ( name in options )
+                               jQuery.attr(
+                                       type ?
+                                               this.style :
+                                               this,
+                                       name, jQuery.prop( this, options[ name ], type, i, name )
+                               );
+               });
+       },
+
+       css: function( key, value ) {
+               // ignore negative width and height values
+               if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
+                       value = undefined;
+               return this.attr( key, value, "curCSS" );
+       },
+
+       text: function( text ) {
+               if ( typeof text != "object" && text != null )
+                       return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
+
+               var ret = "";
+
+               jQuery.each( text || this, function(){
+                       jQuery.each( this.childNodes, function(){
+                               if ( this.nodeType != 8 )
+                                       ret += this.nodeType != 1 ?
+                                               this.nodeValue :
+                                               jQuery.fn.text( [ this ] );
+                       });
+               });
+
+               return ret;
+       },
+
+       wrapAll: function( html ) {
+               if ( this[0] )
+                       // The elements to wrap the target around
+                       jQuery( html, this[0].ownerDocument )
+                               .clone()
+                               .insertBefore( this[0] )
+                               .map(function(){
+                                       var elem = this;
+
+                                       while ( elem.firstChild )
+                                               elem = elem.firstChild;
+
+                                       return elem;
+                               })
+                               .append(this);
+
+               return this;
+       },
+
+       wrapInner: function( html ) {
+               return this.each(function(){
+                       jQuery( this ).contents().wrapAll( html );
+               });
+       },
+
+       wrap: function( html ) {
+               return this.each(function(){
+                       jQuery( this ).wrapAll( html );
+               });
+       },
+
+       append: function() {
+               return this.domManip(arguments, true, false, function(elem){
+                       if (this.nodeType == 1)
+                               this.appendChild( elem );
+               });
+       },
+
+       prepend: function() {
+               return this.domManip(arguments, true, true, function(elem){
+                       if (this.nodeType == 1)
+                               this.insertBefore( elem, this.firstChild );
+               });
+       },
+
+       before: function() {
+               return this.domManip(arguments, false, false, function(elem){
+                       this.parentNode.insertBefore( elem, this );
+               });
+       },
+
+       after: function() {
+               return this.domManip(arguments, false, true, function(elem){
+                       this.parentNode.insertBefore( elem, this.nextSibling );
+               });
+       },
+
+       end: function() {
+               return this.prevObject || jQuery( [] );
+       },
+
+       find: function( selector ) {
+               var elems = jQuery.map(this, function(elem){
+                       return jQuery.find( selector, elem );
+               });
+
+               return this.pushStack( /[^+>] [^+>]/.test( selector ) || selector.indexOf("..") > -1 ?
+                       jQuery.unique( elems ) :
+                       elems );
+       },
+
+       clone: function( events ) {
+               // Do the clone
+               var ret = this.map(function(){
+                       if ( jQuery.browser.msie && !jQuery.isXMLDoc(this) ) {
+                               // IE copies events bound via attachEvent when
+                               // using cloneNode. Calling detachEvent on the
+                               // clone will also remove the events from the orignal
+                               // In order to get around this, we use innerHTML.
+                               // Unfortunately, this means some modifications to
+                               // attributes in IE that are actually only stored
+                               // as properties will not be copied (such as the
+                               // the name attribute on an input).
+                               var clone = this.cloneNode(true),
+                                       container = document.createElement("div");
+                               container.appendChild(clone);
+                               return jQuery.clean([container.innerHTML])[0];
+                       } else
+                               return this.cloneNode(true);
+               });
+
+               // Need to set the expando to null on the cloned set if it exists
+               // removeData doesn't work here, IE removes it from the original as well
+               // this is primarily for IE but the data expando shouldn't be copied over in any browser
+               var clone = ret.find("*").andSelf().each(function(){
+                       if ( this[ expando ] != undefined )
+                               this[ expando ] = null;
+               });
+
+               // Copy the events from the original to the clone
+               if ( events === true )
+                       this.find("*").andSelf().each(function(i){
+                               if (this.nodeType == 3)
+                                       return;
+                               var events = jQuery.data( this, "events" );
+
+                               for ( var type in events )
+                                       for ( var handler in events[ type ] )
+                                               jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data );
+                       });
+
+               // Return the cloned set
+               return ret;
+       },
+
+       filter: function( selector ) {
+               return this.pushStack(
+                       jQuery.isFunction( selector ) &&
+                       jQuery.grep(this, function(elem, i){
+                               return selector.call( elem, i );
+                       }) ||
+
+                       jQuery.multiFilter( selector, this ) );
+       },
+
+       not: function( selector ) {
+               if ( selector.constructor == String )
+                       // test special case where just one selector is passed in
+                       if ( isSimple.test( selector ) )
+                               return this.pushStack( jQuery.multiFilter( selector, this, true ) );
+                       else
+                               selector = jQuery.multiFilter( selector, this );
+
+               var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
+               return this.filter(function() {
+                       return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
+               });
+       },
+
+       add: function( selector ) {
+               return this.pushStack( jQuery.unique( jQuery.merge(
+                       this.get(),
+                       typeof selector == 'string' ?
+                               jQuery( selector ) :
+                               jQuery.makeArray( selector )
+               )));
+       },
+
+       is: function( selector ) {
+               return !!selector && jQuery.multiFilter( selector, this ).length > 0;
+       },
+
+       hasClass: function( selector ) {
+               return this.is( "." + selector );
+       },
+
+       val: function( value ) {
+               if ( value == undefined ) {
+
+                       if ( this.length ) {
+                               var elem = this[0];
+
+                               // We need to handle select boxes special
+                               if ( jQuery.nodeName( elem, "select" ) ) {
+                                       var index = elem.selectedIndex,
+                                               values = [],
+                                               options = elem.options,
+                                               one = elem.type == "select-one";
+
+                                       // Nothing was selected
+                                       if ( index < 0 )
+                                               return null;
+
+                                       // Loop through all the selected options
+                                       for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
+                                               var option = options[ i ];
+
+                                               if ( option.selected ) {
+                                                       // Get the specifc value for the option
+                                                       value = jQuery.browser.msie && !option.attributes.value.specified ? option.text : option.value;
+
+                                                       // We don't need an array for one selects
+                                                       if ( one )
+                                                               return value;
+
+                                                       // Multi-Selects return an array
+                                                       values.push( value );
+                                               }
+                                       }
+
+                                       return values;
+
+                               // Everything else, we just grab the value
+                               } else
+                                       return (this[0].value || "").replace(/\r/g, "");
+
+                       }
+
+                       return undefined;
+               }
+
+               if( value.constructor == Number )
+                       value += '';
+
+               return this.each(function(){
+                       if ( this.nodeType != 1 )
+                               return;
+
+                       if ( value.constructor == Array && /radio|checkbox/.test( this.type ) )
+                               this.checked = (jQuery.inArray(this.value, value) >= 0 ||
+                                       jQuery.inArray(this.name, value) >= 0);
+
+                       else if ( jQuery.nodeName( this, "select" ) ) {
+                               var values = jQuery.makeArray(value);
+
+                               jQuery( "option", this ).each(function(){
+                                       this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
+                                               jQuery.inArray( this.text, values ) >= 0);
+                               });
+
+                               if ( !values.length )
+                                       this.selectedIndex = -1;
+
+                       } else
+                               this.value = value;
+               });
+       },
+
+       html: function( value ) {
+               return value == undefined ?
+                       (this[0] ?
+                               this[0].innerHTML :
+                               null) :
+                       this.empty().append( value );
+       },
+
+       replaceWith: function( value ) {
+               return this.after( value ).remove();
+       },
+
+       eq: function( i ) {
+               return this.slice( i, i + 1 );
+       },
+
+       slice: function() {
+               return this.pushStack( Array.prototype.slice.apply( this, arguments ) );
+       },
+
+       map: function( callback ) {
+               return this.pushStack( jQuery.map(this, function(elem, i){
+                       return callback.call( elem, i, elem );
+               }));
+       },
+
+       andSelf: function() {
+               return this.add( this.prevObject );
+       },
+
+       data: function( key, value ){
+               var parts = key.split(".");
+               parts[1] = parts[1] ? "." + parts[1] : "";
+
+               if ( value === undefined ) {
+                       var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
+
+                       if ( data === undefined && this.length )
+                               data = jQuery.data( this[0], key );
+
+                       return data === undefined && parts[1] ?
+                               this.data( parts[0] ) :
+                               data;
+               } else
+                       return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
+                               jQuery.data( this, key, value );
+                       });
+       },
+
+       removeData: function( key ){
+               return this.each(function(){
+                       jQuery.removeData( this, key );
+               });
+       },
+
+       domManip: function( args, table, reverse, callback ) {
+               var clone = this.length > 1, elems;
+
+               return this.each(function(){
+                       if ( !elems ) {
+                               elems = jQuery.clean( args, this.ownerDocument );
+
+                               if ( reverse )
+                                       elems.reverse();
+                       }
+
+                       var obj = this;
+
+                       if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) )
+                               obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") );
+
+                       var scripts = jQuery( [] );
+
+                       jQuery.each(elems, function(){
+                               var elem = clone ?
+                                       jQuery( this ).clone( true )[0] :
+                                       this;
+
+                               // execute all scripts after the elements have been injected
+                               if ( jQuery.nodeName( elem, "script" ) )
+                                       scripts = scripts.add( elem );
+                               else {
+                                       // Remove any inner scripts for later evaluation
+                                       if ( elem.nodeType == 1 )
+                                               scripts = scripts.add( jQuery( "script", elem ).remove() );
+
+                                       // Inject the elements into the document
+                                       callback.call( obj, elem );
+                               }
+                       });
+
+                       scripts.each( evalScript );
+               });
+       }
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+function evalScript( i, elem ) {
+       if ( elem.src )
+               jQuery.ajax({
+                       url: elem.src,
+                       async: false,
+                       dataType: "script"
+               });
+
+       else
+               jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
+
+       if ( elem.parentNode )
+               elem.parentNode.removeChild( elem );
+}
+
+function now(){
+       return +new Date;
+}
+
+jQuery.extend = jQuery.fn.extend = function() {
+       // copy reference to target object
+       var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
+
+       // Handle a deep copy situation
+       if ( target.constructor == Boolean ) {
+               deep = target;
+               target = arguments[1] || {};
+               // skip the boolean and the target
+               i = 2;
+       }
+
+       // Handle case when target is a string or something (possible in deep copy)
+       if ( typeof target != "object" && typeof target != "function" )
+               target = {};
+
+       // extend jQuery itself if only one argument is passed
+       if ( length == i ) {
+               target = this;
+               --i;
+       }
+
+       for ( ; i < length; i++ )
+               // Only deal with non-null/undefined values
+               if ( (options = arguments[ i ]) != null )
+                       // Extend the base object
+                       for ( var name in options ) {
+                               var src = target[ name ], copy = options[ name ];
+
+                               // Prevent never-ending loop
+                               if ( target === copy )
+                                       continue;
+
+                               // Recurse if we're merging object values
+                               if ( deep && copy && typeof copy == "object" && !copy.nodeType )
+                                       target[ name ] = jQuery.extend( deep, 
+                                               // Never move original objects, clone them
+                                               src || ( copy.length != null ? [ ] : { } )
+                                       , copy );
+
+                               // Don't bring in undefined values
+                               else if ( copy !== undefined )
+                                       target[ name ] = copy;
+
+                       }
+
+       // Return the modified object
+       return target;
+};
+
+var expando = "jQuery" + now(), uuid = 0, windowData = {},
+       // exclude the following css properties to add px
+       exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
+       // cache defaultView
+       defaultView = document.defaultView || {};
+
+jQuery.extend({
+       noConflict: function( deep ) {
+               window.$ = _$;
+
+               if ( deep )
+                       window.jQuery = _jQuery;
+
+               return jQuery;
+       },
+
+       // See test/unit/core.js for details concerning this function.
+       isFunction: function( fn ) {
+               return !!fn && typeof fn != "string" && !fn.nodeName &&
+                       fn.constructor != Array && /^[\s[]?function/.test( fn + "" );
+       },
+
+       // check if an element is in a (or is an) XML document
+       isXMLDoc: function( elem ) {
+               return elem.documentElement && !elem.body ||
+                       elem.tagName && elem.ownerDocument && !elem.ownerDocument.body;
+       },
+
+       // Evalulates a script in a global context
+       globalEval: function( data ) {
+               data = jQuery.trim( data );
+
+               if ( data ) {
+                       // Inspired by code by Andrea Giammarchi
+                       // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
+                       var head = document.getElementsByTagName("head")[0] || document.documentElement,
+                               script = document.createElement("script");
+
+                       script.type = "text/javascript";
+                       if ( jQuery.browser.msie )
+                               script.text = data;
+                       else
+                               script.appendChild( document.createTextNode( data ) );
+
+                       // Use insertBefore instead of appendChild  to circumvent an IE6 bug.
+                       // This arises when a base node is used (#2709).
+                       head.insertBefore( script, head.firstChild );
+                       head.removeChild( script );
+               }
+       },
+
+       nodeName: function( elem, name ) {
+               return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
+       },
+
+       cache: {},
+
+       data: function( elem, name, data ) {
+               elem = elem == window ?
+                       windowData :
+                       elem;
+
+               var id = elem[ expando ];
+
+               // Compute a unique ID for the element
+               if ( !id )
+                       id = elem[ expando ] = ++uuid;
+
+               // Only generate the data cache if we're
+               // trying to access or manipulate it
+               if ( name && !jQuery.cache[ id ] )
+                       jQuery.cache[ id ] = {};
+
+               // Prevent overriding the named cache with undefined values
+               if ( data !== undefined )
+                       jQuery.cache[ id ][ name ] = data;
+
+               // Return the named cache data, or the ID for the element
+               return name ?
+                       jQuery.cache[ id ][ name ] :
+                       id;
+       },
+
+       removeData: function( elem, name ) {
+               elem = elem == window ?
+                       windowData :
+                       elem;
+
+               var id = elem[ expando ];
+
+               // If we want to remove a specific section of the element's data
+               if ( name ) {
+                       if ( jQuery.cache[ id ] ) {
+                               // Remove the section of cache data
+                               delete jQuery.cache[ id ][ name ];
+
+                               // If we've removed all the data, remove the element's cache
+                               name = "";
+
+                               for ( name in jQuery.cache[ id ] )
+                                       break;
+
+                               if ( !name )
+                                       jQuery.removeData( elem );
+                       }
+
+               // Otherwise, we want to remove all of the element's data
+               } else {
+                       // Clean up the element expando
+                       try {
+                               delete elem[ expando ];
+                       } catch(e){
+                               // IE has trouble directly removing the expando
+                               // but it's ok with using removeAttribute
+                               if ( elem.removeAttribute )
+                                       elem.removeAttribute( expando );
+                       }
+
+                       // Completely remove the data cache
+                       delete jQuery.cache[ id ];
+               }
+       },
+
+       // args is for internal usage only
+       each: function( object, callback, args ) {
+               var name, i = 0, length = object.length;
+
+               if ( args ) {
+                       if ( length == undefined ) {
+                               for ( name in object )
+                                       if ( callback.apply( object[ name ], args ) === false )
+                                               break;
+                       } else
+                               for ( ; i < length; )
+                                       if ( callback.apply( object[ i++ ], args ) === false )
+                                               break;
+
+               // A special, fast, case for the most common use of each
+               } else {
+                       if ( length == undefined ) {
+                               for ( name in object )
+                                       if ( callback.call( object[ name ], name, object[ name ] ) === false )
+                                               break;
+                       } else
+                               for ( var value = object[0];
+                                       i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
+               }
+
+               return object;
+       },
+
+       prop: function( elem, value, type, i, name ) {
+               // Handle executable functions
+               if ( jQuery.isFunction( value ) )
+                       value = value.call( elem, i );
+
+               // Handle passing in a number to a CSS property
+               return value && value.constructor == Number && type == "curCSS" && !exclude.test( name ) ?
+                       value + "px" :
+                       value;
+       },
+
+       className: {
+               // internal only, use addClass("class")
+               add: function( elem, classNames ) {
+                       jQuery.each((classNames || "").split(/\s+/), function(i, className){
+                               if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
+                                       elem.className += (elem.className ? " " : "") + className;
+                       });
+               },
+
+               // internal only, use removeClass("class")
+               remove: function( elem, classNames ) {
+                       if (elem.nodeType == 1)
+                               elem.className = classNames != undefined ?
+                                       jQuery.grep(elem.className.split(/\s+/), function(className){
+                                               return !jQuery.className.has( classNames, className );
+                                       }).join(" ") :
+                                       "";
+               },
+
+               // internal only, use hasClass("class")
+               has: function( elem, className ) {
+                       return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
+               }
+       },
+
+       // A method for quickly swapping in/out CSS properties to get correct calculations
+       swap: function( elem, options, callback ) {
+               var old = {};
+               // Remember the old values, and insert the new ones
+               for ( var name in options ) {
+                       old[ name ] = elem.style[ name ];
+                       elem.style[ name ] = options[ name ];
+               }
+
+               callback.call( elem );
+
+               // Revert the old values
+               for ( var name in options )
+                       elem.style[ name ] = old[ name ];
+       },
+
+       css: function( elem, name, force ) {
+               if ( name == "width" || name == "height" ) {
+                       var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
+
+                       function getWH() {
+                               val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
+                               var padding = 0, border = 0;
+                               jQuery.each( which, function() {
+                                       padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
+                                       border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
+                               });
+                               val -= Math.round(padding + border);
+                       }
+
+                       if ( jQuery(elem).is(":visible") )
+                               getWH();
+                       else
+                               jQuery.swap( elem, props, getWH );
+
+                       return Math.max(0, val);
+               }
+
+               return jQuery.curCSS( elem, name, force );
+       },
+
+       curCSS: function( elem, name, force ) {
+               var ret, style = elem.style;
+
+               // A helper method for determining if an element's values are broken
+               function color( elem ) {
+                       if ( !jQuery.browser.safari )
+                               return false;
+
+                       // defaultView is cached
+                       var ret = defaultView.getComputedStyle( elem, null );
+                       return !ret || ret.getPropertyValue("color") == "";
+               }
+
+               // We need to handle opacity special in IE
+               if ( name == "opacity" && jQuery.browser.msie ) {
+                       ret = jQuery.attr( style, "opacity" );
+
+                       return ret == "" ?
+                               "1" :
+                               ret;
+               }
+               // Opera sometimes will give the wrong display answer, this fixes it, see #2037
+               if ( jQuery.browser.opera && name == "display" ) {
+                       var save = style.outline;
+                       style.outline = "0 solid black";
+                       style.outline = save;
+               }
+
+               // Make sure we're using the right name for getting the float value
+               if ( name.match( /float/i ) )
+                       name = styleFloat;
+
+               if ( !force && style && style[ name ] )
+                       ret = style[ name ];
+
+               else if ( defaultView.getComputedStyle ) {
+
+                       // Only "float" is needed here
+                       if ( name.match( /float/i ) )
+                               name = "float";
+
+                       name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
+
+                       var computedStyle = defaultView.getComputedStyle( elem, null );
+
+                       if ( computedStyle && !color( elem ) )
+                               ret = computedStyle.getPropertyValue( name );
+
+                       // If the element isn't reporting its values properly in Safari
+                       // then some display: none elements are involved
+                       else {
+                               var swap = [], stack = [], a = elem, i = 0;
+
+                               // Locate all of the parent display: none elements
+                               for ( ; a && color(a); a = a.parentNode )
+                                       stack.unshift(a);
+
+                               // Go through and make them visible, but in reverse
+                               // (It would be better if we knew the exact display type that they had)
+                               for ( ; i < stack.length; i++ )
+                                       if ( color( stack[ i ] ) ) {
+                                               swap[ i ] = stack[ i ].style.display;
+                                               stack[ i ].style.display = "block";
+                                       }
+
+                               // Since we flip the display style, we have to handle that
+                               // one special, otherwise get the value
+                               ret = name == "display" && swap[ stack.length - 1 ] != null ?
+                                       "none" :
+                                       ( computedStyle && computedStyle.getPropertyValue( name ) ) || "";
+
+                               // Finally, revert the display styles back
+                               for ( i = 0; i < swap.length; i++ )
+                                       if ( swap[ i ] != null )
+                                               stack[ i ].style.display = swap[ i ];
+                       }
+
+                       // We should always get a number back from opacity
+                       if ( name == "opacity" && ret == "" )
+                               ret = "1";
+
+               } else if ( elem.currentStyle ) {
+                       var camelCase = name.replace(/\-(\w)/g, function(all, letter){
+                               return letter.toUpperCase();
+                       });
+
+                       ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
+
+                       // From the awesome hack by Dean Edwards
+                       // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+                       // If we're not dealing with a regular pixel number
+                       // but a number that has a weird ending, we need to convert it to pixels
+                       if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
+                               // Remember the original values
+                               var left = style.left, rsLeft = elem.runtimeStyle.left;
+
+                               // Put in the new values to get a computed value out
+                               elem.runtimeStyle.left = elem.currentStyle.left;
+                               style.left = ret || 0;
+                               ret = style.pixelLeft + "px";
+
+                               // Revert the changed values
+                               style.left = left;
+                               elem.runtimeStyle.left = rsLeft;
+                       }
+               }
+
+               return ret;
+       },
+
+       clean: function( elems, context ) {
+               var ret = [];
+               context = context || document;
+               // !context.createElement fails in IE with an error but returns typeof 'object'
+               if (typeof context.createElement == 'undefined')
+                       context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
+
+               jQuery.each(elems, function(i, elem){
+                       if ( !elem )
+                               return;
+
+                       if ( elem.constructor == Number )
+                               elem += '';
+
+                       // Convert html string into DOM nodes
+                       if ( typeof elem == "string" ) {
+                               // Fix "XHTML"-style tags in all browsers
+                               elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
+                                       return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
+                                               all :
+                                               front + "></" + tag + ">";
+                               });
+
+                               // Trim whitespace, otherwise indexOf won't work as expected
+                               var tags = jQuery.trim( elem ).toLowerCase(), div = context.createElement("div");
+
+                               var wrap =
+                                       // option or optgroup
+                                       !tags.indexOf("<opt") &&
+                                       [ 1, "<select multiple='multiple'>", "</select>" ] ||
+
+                                       !tags.indexOf("<leg") &&
+                                       [ 1, "<fieldset>", "</fieldset>" ] ||
+
+                                       tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
+                                       [ 1, "<table>", "</table>" ] ||
+
+                                       !tags.indexOf("<tr") &&
+                                       [ 2, "<table><tbody>", "</tbody></table>" ] ||
+
+                                       // <thead> matched above
+                                       (!tags.indexOf("<td") || !tags.indexOf("<th")) &&
+                                       [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
+
+                                       !tags.indexOf("<col") &&
+                                       [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
+
+                                       // IE can't serialize <link> and <script> tags normally
+                                       jQuery.browser.msie &&
+                                       [ 1, "div<div>", "</div>" ] ||
+
+                                       [ 0, "", "" ];
+
+                               // Go to html and back, then peel off extra wrappers
+                               div.innerHTML = wrap[1] + elem + wrap[2];
+
+                               // Move to the right depth
+                               while ( wrap[0]-- )
+                                       div = div.lastChild;
+
+                               // Remove IE's autoinserted <tbody> from table fragments
+                               if ( jQuery.browser.msie ) {
+
+                                       // String was a <table>, *may* have spurious <tbody>
+                                       var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ?
+                                               div.firstChild && div.firstChild.childNodes :
+
+                                               // String was a bare <thead> or <tfoot>
+                                               wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ?
+                                                       div.childNodes :
+                                                       [];
+
+                                       for ( var j = tbody.length - 1; j >= 0 ; --j )
+                                               if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
+                                                       tbody[ j ].parentNode.removeChild( tbody[ j ] );
+
+                                       // IE completely kills leading whitespace when innerHTML is used
+                                       if ( /^\s/.test( elem ) )
+                                               div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
+
+                               }
+
+                               elem = jQuery.makeArray( div.childNodes );
+                       }
+
+                       if ( elem.length === 0 && (!jQuery.nodeName( elem, "form" ) && !jQuery.nodeName( elem, "select" )) )
+                               return;
+
+                       if ( elem[0] == undefined || jQuery.nodeName( elem, "form" ) || elem.options )
+                               ret.push( elem );
+
+                       else
+                               ret = jQuery.merge( ret, elem );
+
+               });
+
+               return ret;
+       },
+
+       attr: function( elem, name, value ) {
+               // don't set attributes on text and comment nodes
+               if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
+                       return undefined;
+
+               var notxml = !jQuery.isXMLDoc( elem ),
+                       // Whether we are setting (or getting)
+                       set = value !== undefined,
+                       msie = jQuery.browser.msie;
+
+               // Try to normalize/fix the name
+               name = notxml && jQuery.props[ name ] || name;
+
+               // Only do all the following if this is a node (faster for style)
+               // IE elem.getAttribute passes even for style
+               if ( elem.tagName ) {
+
+                       // These attributes require special treatment
+                       var special = /href|src|style/.test( name );
+
+                       // Safari mis-reports the default selected property of a hidden option
+                       // Accessing the parent's selectedIndex property fixes it
+                       if ( name == "selected" && jQuery.browser.safari )
+                               elem.parentNode.selectedIndex;
+
+                       // If applicable, access the attribute via the DOM 0 way
+                       if ( name in elem && notxml && !special ) {
+                               if ( set ){
+                                       // We can't allow the type property to be changed (since it causes problems in IE)
+                                       if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
+                                               throw "type property can't be changed";
+
+                                       elem[ name ] = value;
+                               }
+
+                               // browsers index elements by id/name on forms, give priority to attributes.
+                               if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
+                                       return elem.getAttributeNode( name ).nodeValue;
+
+                               return elem[ name ];
+                       }
+
+                       if ( msie && notxml &&  name == "style" )
+                               return jQuery.attr( elem.style, "cssText", value );
+
+                       if ( set )
+                               // convert the value to a string (all browsers do this but IE) see #1070
+                               elem.setAttribute( name, "" + value );
+
+                       var attr = msie && notxml && special
+                                       // Some attributes require a special call on IE
+                                       ? elem.getAttribute( name, 2 )
+                                       : elem.getAttribute( name );
+
+                       // Non-existent attributes return null, we normalize to undefined
+                       return attr === null ? undefined : attr;
+               }
+
+               // elem is actually elem.style ... set the style
+
+               // IE uses filters for opacity
+               if ( msie && name == "opacity" ) {
+                       if ( set ) {
+                               // IE has trouble with opacity if it does not have layout
+                               // Force it by setting the zoom level
+                               elem.zoom = 1;
+
+                               // Set the alpha filter to set the opacity
+                               elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
+                                       (parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
+                       }
+
+                       return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
+                               (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
+                               "";
+               }
+
+               name = name.replace(/-([a-z])/ig, function(all, letter){
+                       return letter.toUpperCase();
+               });
+
+               if ( set )
+                       elem[ name ] = value;
+
+               return elem[ name ];
+       },
+
+       trim: function( text ) {
+               return (text || "").replace( /^\s+|\s+$/g, "" );
+       },
+
+       makeArray: function( array ) {
+               var ret = [];
+
+               if( array != null ){
+                       var i = array.length;
+                       //the window, strings and functions also have 'length'
+                       if( i == null || array.split || array.setInterval || array.call )
+                               ret[0] = array;
+                       else
+                               while( i )
+                                       ret[--i] = array[i];
+               }
+
+               return ret;
+       },
+
+       inArray: function( elem, array ) {
+               for ( var i = 0, length = array.length; i < length; i++ )
+               // Use === because on IE, window == document
+                       if ( array[ i ] === elem )
+                               return i;
+
+               return -1;
+       },
+
+       merge: function( first, second ) {
+               // We have to loop this way because IE & Opera overwrite the length
+               // expando of getElementsByTagName
+               var i = 0, elem, pos = first.length;
+               // Also, we need to make sure that the correct elements are being returned
+               // (IE returns comment nodes in a '*' query)
+               if ( jQuery.browser.msie ) {
+                       while ( elem = second[ i++ ] )
+                               if ( elem.nodeType != 8 )
+                                       first[ pos++ ] = elem;
+
+               } else
+                       while ( elem = second[ i++ ] )
+                               first[ pos++ ] = elem;
+
+               return first;
+       },
+
+       unique: function( array ) {
+               var ret = [], done = {};
+
+               try {
+
+                       for ( var i = 0, length = array.length; i < length; i++ ) {
+                               var id = jQuery.data( array[ i ] );
+
+                               if ( !done[ id ] ) {
+                                       done[ id ] = true;
+                                       ret.push( array[ i ] );
+                               }
+                       }
+
+               } catch( e ) {
+                       ret = array;
+               }
+
+               return ret;
+       },
+
+       grep: function( elems, callback, inv ) {
+               var ret = [];
+
+               // Go through the array, only saving the items
+               // that pass the validator function
+               for ( var i = 0, length = elems.length; i < length; i++ )
+                       if ( !inv != !callback( elems[ i ], i ) )
+                               ret.push( elems[ i ] );
+
+               return ret;
+       },
+
+       map: function( elems, callback ) {
+               var ret = [];
+
+               // Go through the array, translating each of the items to their
+               // new value (or values).
+               for ( var i = 0, length = elems.length; i < length; i++ ) {
+                       var value = callback( elems[ i ], i );
+
+                       if ( value != null )
+                               ret[ ret.length ] = value;
+               }
+
+               return ret.concat.apply( [], ret );
+       }
+});
+
+var userAgent = navigator.userAgent.toLowerCase();
+
+// Figure out what browser is being used
+jQuery.browser = {
+       version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1],
+       safari: /webkit/.test( userAgent ),
+       opera: /opera/.test( userAgent ),
+       msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
+       mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
+};
+
+var styleFloat = jQuery.browser.msie ?
+       "styleFloat" :
+       "cssFloat";
+
+jQuery.extend({
+       // Check to see if the W3C box model is being used
+       boxModel: !jQuery.browser.msie || document.compatMode == "CSS1Compat",
+
+       props: {
+               "for": "htmlFor",
+               "class": "className",
+               "float": styleFloat,
+               cssFloat: styleFloat,
+               styleFloat: styleFloat,
+               readonly: "readOnly",
+               maxlength: "maxLength",
+               cellspacing: "cellSpacing"
+       }
+});
+
+jQuery.each({
+       parent: function(elem){return elem.parentNode;},
+       parents: function(elem){return jQuery.dir(elem,"parentNode");},
+       next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
+       prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
+       nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
+       prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
+       siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
+       children: function(elem){return jQuery.sibling(elem.firstChild);},
+       contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
+}, function(name, fn){
+       jQuery.fn[ name ] = function( selector ) {
+               var ret = jQuery.map( this, fn );
+
+               if ( selector && typeof selector == "string" )
+                       ret = jQuery.multiFilter( selector, ret );
+
+               return this.pushStack( jQuery.unique( ret ) );
+       };
+});
+
+jQuery.each({
+       appendTo: "append",
+       prependTo: "prepend",
+       insertBefore: "before",
+       insertAfter: "after",
+       replaceAll: "replaceWith"
+}, function(name, original){
+       jQuery.fn[ name ] = function() {
+               var args = arguments;
+
+               return this.each(function(){
+                       for ( var i = 0, length = args.length; i < length; i++ )
+                               jQuery( args[ i ] )[ original ]( this );
+               });
+       };
+});
+
+jQuery.each({
+       removeAttr: function( name ) {
+               jQuery.attr( this, name, "" );
+               if (this.nodeType == 1)
+                       this.removeAttribute( name );
+       },
+
+       addClass: function( classNames ) {
+               jQuery.className.add( this, classNames );
+       },
+
+       removeClass: function( classNames ) {
+               jQuery.className.remove( this, classNames );
+       },
+
+       toggleClass: function( classNames ) {
+               jQuery.className[ jQuery.className.has( this, classNames ) ? "remove" : "add" ]( this, classNames );
+       },
+
+       remove: function( selector ) {
+               if ( !selector || jQuery.filter( selector, [ this ] ).r.length ) {
+                       // Prevent memory leaks
+                       jQuery( "*", this ).add(this).each(function(){
+                               jQuery.event.remove(this);
+                               jQuery.removeData(this);
+                       });
+                       if (this.parentNode)
+                               this.parentNode.removeChild( this );
+               }
+       },
+
+       empty: function() {
+               // Remove element nodes and prevent memory leaks
+               jQuery( ">*", this ).remove();
+
+               // Remove any remaining nodes
+               while ( this.firstChild )
+                       this.removeChild( this.firstChild );
+       }
+}, function(name, fn){
+       jQuery.fn[ name ] = function(){
+               return this.each( fn, arguments );
+       };
+});
+
+jQuery.each([ "Height", "Width" ], function(i, name){
+       var type = name.toLowerCase();
+
+       jQuery.fn[ type ] = function( size ) {
+               // Get window width or height
+               return this[0] == window ?
+                       // Opera reports document.body.client[Width/Height] properly in both quirks and standards
+                       jQuery.browser.opera && document.body[ "client" + name ] ||
+
+                       // Safari reports inner[Width/Height] just fine (Mozilla and Opera include scroll bar widths)
+                       jQuery.browser.safari && window[ "inner" + name ] ||
+
+                       // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
+                       document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] || document.body[ "client" + name ] :
+
+                       // Get document width or height
+                       this[0] == document ?
+                               // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
+                               Math.max(
+                                       Math.max(document.body["scroll" + name], document.documentElement["scroll" + name]),
+                                       Math.max(document.body["offset" + name], document.documentElement["offset" + name])
+                               ) :
+
+                               // Get or set width or height on the element
+                               size == undefined ?
+                                       // Get width or height on the element
+                                       (this.length ? jQuery.css( this[0], type ) : null) :
+
+                                       // Set the width or height on the element (default to pixels if value is unitless)
+                                       this.css( type, size.constructor == String ? size : size + "px" );
+       };
+});
+
+// Helper function used by the dimensions and offset modules
+function num(elem, prop) {
+       return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
+}var chars = jQuery.browser.safari && parseInt(jQuery.browser.version) < 417 ?
+               "(?:[\\w*_-]|\\\\.)" :
+               "(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",
+       quickChild = new RegExp("^>\\s*(" + chars + "+)"),
+       quickID = new RegExp("^(" + chars + "+)(#)(" + chars + "+)"),
+       quickClass = new RegExp("^([#.]?)(" + chars + "*)");
+
+jQuery.extend({
+       expr: {
+               "": function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},
+               "#": function(a,i,m){return a.getAttribute("id")==m[2];},
+               ":": {
+                       // Position Checks
+                       lt: function(a,i,m){return i<m[3]-0;},
+                       gt: function(a,i,m){return i>m[3]-0;},
+                       nth: function(a,i,m){return m[3]-0==i;},
+                       eq: function(a,i,m){return m[3]-0==i;},
+                       first: function(a,i){return i==0;},
+                       last: function(a,i,m,r){return i==r.length-1;},
+                       even: function(a,i){return i%2==0;},
+                       odd: function(a,i){return i%2;},
+
+                       // Child Checks
+                       "first-child": function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},
+                       "last-child": function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},
+                       "only-child": function(a){return !jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},
+
+                       // Parent Checks
+                       parent: function(a){return a.firstChild;},
+                       empty: function(a){return !a.firstChild;},
+
+                       // Text Check
+                       contains: function(a,i,m){return (a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},
+
+                       // Visibility
+                       visible: function(a){return "hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},
+                       hidden: function(a){return "hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},
+
+                       // Form attributes
+                       enabled: function(a){return !a.disabled;},
+                       disabled: function(a){return a.disabled;},
+                       checked: function(a){return a.checked;},
+                       selected: function(a){return a.selected||jQuery.attr(a,"selected");},
+
+                       // Form elements
+                       text: function(a){return "text"==a.type;},
+                       radio: function(a){return "radio"==a.type;},
+                       checkbox: function(a){return "checkbox"==a.type;},
+                       file: function(a){return "file"==a.type;},
+                       password: function(a){return "password"==a.type;},
+                       submit: function(a){return "submit"==a.type;},
+                       image: function(a){return "image"==a.type;},
+                       reset: function(a){return "reset"==a.type;},
+                       button: function(a){return "button"==a.type||jQuery.nodeName(a,"button");},
+                       input: function(a){return /input|select|textarea|button/i.test(a.nodeName);},
+
+                       // :has()
+                       has: function(a,i,m){return jQuery.find(m[3],a).length;},
+
+                       // :header
+                       header: function(a){return /h\d/i.test(a.nodeName);},
+
+                       // :animated
+                       animated: function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}
+               }
+       },
+
+       // The regular expressions that power the parsing engine
+       parse: [
+               // Match: [@value='test'], [@foo]
+               /^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,
+
+               // Match: :contains('foo')
+               /^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,
+
+               // Match: :even, :last-child, #id, .class
+               new RegExp("^([:.#]*)(" + chars + "+)")
+       ],
+
+       multiFilter: function( expr, elems, not ) {
+               var old, cur = [];
+
+               while ( expr && expr != old ) {
+                       old = expr;
+                       var f = jQuery.filter( expr, elems, not );
+                       expr = f.t.replace(/^\s*,\s*/, "" );
+                       cur = not ? elems = f.r : jQuery.merge( cur, f.r );
+               }
+
+               return cur;
+       },
+
+       find: function( t, context ) {
+               // Quickly handle non-string expressions
+               if ( typeof t != "string" )
+                       return [ t ];
+
+               // check to make sure context is a DOM element or a document
+               if ( context && context.nodeType != 1 && context.nodeType != 9)
+                       return [ ];
+
+               // Set the correct context (if none is provided)
+               context = context || document;
+
+               // Initialize the search
+               var ret = [context], done = [], last, nodeName;
+
+               // Continue while a selector expression exists, and while
+               // we're no longer looping upon ourselves
+               while ( t && last != t ) {
+                       var r = [];
+                       last = t;
+
+                       t = jQuery.trim(t);
+
+                       var foundToken = false,
+
+                       // An attempt at speeding up child selectors that
+                       // point to a specific element tag
+                               re = quickChild,
+
+                               m = re.exec(t);
+
+                       if ( m ) {
+                               nodeName = m[1].toUpperCase();
+
+                               // Perform our own iteration and filter
+                               for ( var i = 0; ret[i]; i++ )
+                                       for ( var c = ret[i].firstChild; c; c = c.nextSibling )
+                                               if ( c.nodeType == 1 && (nodeName == "*" || c.nodeName.toUpperCase() == nodeName) )
+                                                       r.push( c );
+
+                               ret = r;
+                               t = t.replace( re, "" );
+                               if ( t.indexOf(" ") == 0 ) continue;
+                               foundToken = true;
+                       } else {
+                               re = /^([>+~])\s*(\w*)/i;
+
+                               if ( (m = re.exec(t)) != null ) {
+                                       r = [];
+
+                                       var merge = {};
+                                       nodeName = m[2].toUpperCase();
+                                       m = m[1];
+
+                                       for ( var j = 0, rl = ret.length; j < rl; j++ ) {
+                                               var n = m == "~" || m == "+" ? ret[j].nextSibling : ret[j].firstChild;
+                                               for ( ; n; n = n.nextSibling )
+                                                       if ( n.nodeType == 1 ) {
+                                                               var id = jQuery.data(n);
+
+                                                               if ( m == "~" && merge[id] ) break;
+
+                                                               if (!nodeName || n.nodeName.toUpperCase() == nodeName ) {
+                                                                       if ( m == "~" ) merge[id] = true;
+                                                                       r.push( n );
+                                                               }
+
+                                                               if ( m == "+" ) break;
+                                                       }
+                                       }
+
+                                       ret = r;
+
+                                       // And remove the token
+                                       t = jQuery.trim( t.replace( re, "" ) );
+                                       foundToken = true;
+                               }
+                       }
+
+                       // See if there's still an expression, and that we haven't already
+                       // matched a token
+                       if ( t && !foundToken ) {
+                               // Handle multiple expressions
+                               if ( !t.indexOf(",") ) {
+                                       // Clean the result set
+                                       if ( context == ret[0] ) ret.shift();
+
+                                       // Merge the result sets
+                                       done = jQuery.merge( done, ret );
+
+                                       // Reset the context
+                                       r = ret = [context];
+
+                                       // Touch up the selector string
+                                       t = " " + t.substr(1,t.length);
+
+                               } else {
+                                       // Optimize for the case nodeName#idName
+                                       var re2 = quickID;
+                                       var m = re2.exec(t);
+
+                                       // Re-organize the results, so that they're consistent
+                                       if ( m ) {
+                                               m = [ 0, m[2], m[3], m[1] ];
+
+                                       } else {
+                                               // Otherwise, do a traditional filter check for
+                                               // ID, class, and element selectors
+                                               re2 = quickClass;
+                                               m = re2.exec(t);
+                                       }
+
+                                       m[2] = m[2].replace(/\\/g, "");
+
+                                       var elem = ret[ret.length-1];
+
+                                       // Try to do a global search by ID, where we can
+                                       if ( m[1] == "#" && elem && elem.getElementById && !jQuery.isXMLDoc(elem) ) {
+                                               // Optimization for HTML document case
+                                               var oid = elem.getElementById(m[2]);
+
+                                               // Do a quick check for the existence of the actual ID attribute
+                                               // to avoid selecting by the name attribute in IE
+                                               // also check to insure id is a string to avoid selecting an element with the name of 'id' inside a form
+                                               if ( (jQuery.browser.msie||jQuery.browser.opera) && oid && typeof oid.id == "string" && oid.id != m[2] )
+                                                       oid = jQuery('[@id="'+m[2]+'"]', elem)[0];
+
+                                               // Do a quick check for node name (where applicable) so
+                                               // that div#foo searches will be really fast
+                                               ret = r = oid && (!m[3] || jQuery.nodeName(oid, m[3])) ? [oid] : [];
+                                       } else {
+                                               // We need to find all descendant elements
+                                               for ( var i = 0; ret[i]; i++ ) {
+                                                       // Grab the tag name being searched for
+                                                       var tag = m[1] == "#" && m[3] ? m[3] : m[1] != "" || m[0] == "" ? "*" : m[2];
+
+                                                       // Handle IE7 being really dumb about <object>s
+                                                       if ( tag == "*" && ret[i].nodeName.toLowerCase() == "object" )
+                                                               tag = "param";
+
+                                                       r = jQuery.merge( r, ret[i].getElementsByTagName( tag ));
+                                               }
+
+                                               // It's faster to filter by class and be done with it
+                                               if ( m[1] == "." )
+                                                       r = jQuery.classFilter( r, m[2] );
+
+                                               // Same with ID filtering
+                                               if ( m[1] == "#" ) {
+                                                       var tmp = [];
+
+                                                       // Try to find the element with the ID
+                                                       for ( var i = 0; r[i]; i++ )
+                                                               if ( r[i].getAttribute("id") == m[2] ) {
+                                                                       tmp = [ r[i] ];
+                                                                       break;
+                                                               }
+
+                                                       r = tmp;
+                                               }
+
+                                               ret = r;
+                                       }
+
+                                       t = t.replace( re2, "" );
+                               }
+
+                       }
+
+                       // If a selector string still exists
+                       if ( t ) {
+                               // Attempt to filter it
+                               var val = jQuery.filter(t,r);
+                               ret = r = val.r;
+                               t = jQuery.trim(val.t);
+                       }
+               }
+
+               // An error occurred with the selector;
+               // just return an empty set instead
+               if ( t )
+                       ret = [];
+
+               // Remove the root context
+               if ( ret && context == ret[0] )
+                       ret.shift();
+
+               // And combine the results
+               done = jQuery.merge( done, ret );
+
+               return done;
+       },
+
+       classFilter: function(r,m,not){
+               m = " " + m + " ";
+               var tmp = [];
+               for ( var i = 0; r[i]; i++ ) {
+                       var pass = (" " + r[i].className + " ").indexOf( m ) >= 0;
+                       if ( !not && pass || not && !pass )
+                               tmp.push( r[i] );
+               }
+               return tmp;
+       },
+
+       filter: function(t,r,not) {
+               var last;
+
+               // Look for common filter expressions
+               while ( t && t != last ) {
+                       last = t;
+
+                       var p = jQuery.parse, m;
+
+                       for ( var i = 0; p[i]; i++ ) {
+                               m = p[i].exec( t );
+
+                               if ( m ) {
+                                       // Remove what we just matched
+                                       t = t.substring( m[0].length );
+
+                                       m[2] = m[2].replace(/\\/g, "");
+                                       break;
+                               }
+                       }
+
+                       if ( !m )
+                               break;
+
+                       // :not() is a special case that can be optimized by
+                       // keeping it out of the expression list
+                       if ( m[1] == ":" && m[2] == "not" )
+                               // optimize if only one selector found (most common case)
+                               r = isSimple.test( m[3] ) ?
+                                       jQuery.filter(m[3], r, true).r :
+                                       jQuery( r ).not( m[3] );
+
+                       // We can get a big speed boost by filtering by class here
+                       else if ( m[1] == "." )
+                               r = jQuery.classFilter(r, m[2], not);
+
+                       else if ( m[1] == "[" ) {
+                               var tmp = [], type = m[3];
+
+                               for ( var i = 0, rl = r.length; i < rl; i++ ) {
+                                       var a = r[i], z = a[ jQuery.props[m[2]] || m[2] ];
+
+                                       if ( z == null || /href|src|selected/.test(m[2]) )
+                                               z = jQuery.attr(a,m[2]) || '';
+
+                                       if ( (type == "" && !!z ||
+                                                type == "=" && z == m[5] ||
+                                                type == "!=" && z != m[5] ||
+                                                type == "^=" && z && !z.indexOf(m[5]) ||
+                                                type == "$=" && z.substr(z.length - m[5].length) == m[5] ||
+                                                (type == "*=" || type == "~=") && z.indexOf(m[5]) >= 0) ^ not )
+                                                       tmp.push( a );
+                               }
+
+                               r = tmp;
+
+                       // We can get a speed boost by handling nth-child here
+                       } else if ( m[1] == ":" && m[2] == "nth-child" ) {
+                               var merge = {}, tmp = [],
+                                       // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
+                                       test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
+                                               m[3] == "even" && "2n" || m[3] == "odd" && "2n+1" ||
+                                               !/\D/.test(m[3]) && "0n+" + m[3] || m[3]),
+                                       // calculate the numbers (first)n+(last) including if they are negative
+                                       first = (test[1] + (test[2] || 1)) - 0, last = test[3] - 0;
+
+                               // loop through all the elements left in the jQuery object
+                               for ( var i = 0, rl = r.length; i < rl; i++ ) {
+                                       var node = r[i], parentNode = node.parentNode, id = jQuery.data(parentNode);
+
+                                       if ( !merge[id] ) {
+                                               var c = 1;
+
+                                               for ( var n = parentNode.firstChild; n; n = n.nextSibling )
+                                                       if ( n.nodeType == 1 )
+                                                               n.nodeIndex = c++;
+
+                                               merge[id] = true;
+                                       }
+
+                                       var add = false;
+
+                                       if ( first == 0 ) {
+                                               if ( node.nodeIndex == last )
+                                                       add = true;
+                                       } else if ( (node.nodeIndex - last) % first == 0 && (node.nodeIndex - last) / first >= 0 )
+                                               add = true;
+
+                                       if ( add ^ not )
+                                               tmp.push( node );
+                               }
+
+                               r = tmp;
+
+                       // Otherwise, find the expression to execute
+                       } else {
+                               var fn = jQuery.expr[ m[1] ];
+                               if ( typeof fn == "object" )
+                                       fn = fn[ m[2] ];
+
+                               if ( typeof fn == "string" )
+                                       fn = eval("false||function(a,i){return " + fn + ";}");
+
+                               // Execute it against the current filter
+                               r = jQuery.grep( r, function(elem, i){
+                                       return fn(elem, i, m, r);
+                               }, not );
+                       }
+               }
+
+               // Return an array of filtered elements (r)
+               // and the modified expression string (t)
+               return { r: r, t: t };
+       },
+
+       dir: function( elem, dir ){
+               var matched = [],
+                       cur = elem[dir];
+               while ( cur && cur != document ) {
+                       if ( cur.nodeType == 1 )
+                               matched.push( cur );
+                       cur = cur[dir];
+               }
+               return matched;
+       },
+
+       nth: function(cur,result,dir,elem){
+               result = result || 1;
+               var num = 0;
+
+               for ( ; cur; cur = cur[dir] )
+                       if ( cur.nodeType == 1 && ++num == result )
+                               break;
+
+               return cur;
+       },
+
+       sibling: function( n, elem ) {
+               var r = [];
+
+               for ( ; n; n = n.nextSibling ) {
+                       if ( n.nodeType == 1 && n != elem )
+                               r.push( n );
+               }
+
+               return r;
+       }
+});
+/*
+ * A number of helper functions used for managing events.
+ * Many of the ideas behind this code orignated from
+ * Dean Edwards' addEvent library.
+ */
+jQuery.event = {
+
+       // Bind an event to an element
+       // Original by Dean Edwards
+       add: function(elem, types, handler, data) {
+               if ( elem.nodeType == 3 || elem.nodeType == 8 )
+                       return;
+
+               // For whatever reason, IE has trouble passing the window object
+               // around, causing it to be cloned in the process
+               if ( jQuery.browser.msie && elem.setInterval )
+                       elem = window;
+
+               // Make sure that the function being executed has a unique ID
+               if ( !handler.guid )
+                       handler.guid = this.guid++;
+
+               // if data is passed, bind to handler
+               if( data != undefined ) {
+                       // Create temporary function pointer to original handler
+                       var fn = handler;
+
+                       // Create unique handler function, wrapped around original handler
+                       handler = this.proxy( fn, function() {
+                               // Pass arguments and context to original handler
+                               return fn.apply(this, arguments);
+                       });
+
+                       // Store data in unique handler
+                       handler.data = data;
+               }
+
+               // Init the element's event structure
+               var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
+                       handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
+                               // Handle the second event of a trigger and when
+                               // an event is called after a page has unloaded
+                               if ( typeof jQuery != "undefined" && !jQuery.event.triggered )
+                                       return jQuery.event.handle.apply(arguments.callee.elem, arguments);
+                       });
+               // Add elem as a property of the handle function
+               // This is to prevent a memory leak with non-native
+               // event in IE.
+               handle.elem = elem;
+
+               // Handle multiple events separated by a space
+               // jQuery(...).bind("mouseover mouseout", fn);
+               jQuery.each(types.split(/\s+/), function(index, type) {
+                       // Namespaced event handlers
+                       var parts = type.split(".");
+                       type = parts[0];
+                       handler.type = parts[1];
+
+                       // Get the current list of functions bound to this event
+                       var handlers = events[type];
+
+                       // Init the event handler queue
+                       if (!handlers) {
+                               handlers = events[type] = {};
+
+                               // Check for a special event handler
+                               // Only use addEventListener/attachEvent if the special
+                               // events handler returns false
+                               if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem) === false ) {
+                                       // Bind the global event handler to the element
+                                       if (elem.addEventListener)
+                                               elem.addEventListener(type, handle, false);
+                                       else if (elem.attachEvent)
+                                               elem.attachEvent("on" + type, handle);
+                               }
+                       }
+
+                       // Add the function to the element's handler list
+                       handlers[handler.guid] = handler;
+
+                       // Keep track of which events have been used, for global triggering
+                       jQuery.event.global[type] = true;
+               });
+
+               // Nullify elem to prevent memory leaks in IE
+               elem = null;
+       },
+
+       guid: 1,
+       global: {},
+
+       // Detach an event or set of events from an element
+       remove: function(elem, types, handler) {
+               // don't do events on text and comment nodes
+               if ( elem.nodeType == 3 || elem.nodeType == 8 )
+                       return;
+
+               var events = jQuery.data(elem, "events"), ret, index;
+
+               if ( events ) {
+                       // Unbind all events for the element
+                       if ( types == undefined || (typeof types == "string" && types.charAt(0) == ".") )
+                               for ( var type in events )
+                                       this.remove( elem, type + (types || "") );
+                       else {
+                               // types is actually an event object here
+                               if ( types.type ) {
+                                       handler = types.handler;
+                                       types = types.type;
+                               }
+
+                               // Handle multiple events seperated by a space
+                               // jQuery(...).unbind("mouseover mouseout", fn);
+                               jQuery.each(types.split(/\s+/), function(index, type){
+                                       // Namespaced event handlers
+                                       var parts = type.split(".");
+                                       type = parts[0];
+
+                                       if ( events[type] ) {
+                                               // remove the given handler for the given type
+                                               if ( handler )
+                                                       delete events[type][handler.guid];
+
+                                               // remove all handlers for the given type
+                                               else
+                                                       for ( handler in events[type] )
+                                                               // Handle the removal of namespaced events
+                                                               if ( !parts[1] || events[type][handler].type == parts[1] )
+                                                                       delete events[type][handler];
+
+                                               // remove generic event handler if no more handlers exist
+                                               for ( ret in events[type] ) break;
+                                               if ( !ret ) {
+                                                       if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem) === false ) {
+                                                               if (elem.removeEventListener)
+                                                                       elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
+                                                               else if (elem.detachEvent)
+                                                                       elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
+                                                       }
+                                                       ret = null;
+                                                       delete events[type];
+                                               }
+                                       }
+                               });
+                       }
+
+                       // Remove the expando if it's no longer used
+                       for ( ret in events ) break;
+                       if ( !ret ) {
+                               var handle = jQuery.data( elem, "handle" );
+                               if ( handle ) handle.elem = null;
+                               jQuery.removeData( elem, "events" );
+                               jQuery.removeData( elem, "handle" );
+                       }
+               }
+       },
+
+       trigger: function(type, data, elem, donative, extra) {
+               // Clone the incoming data, if any
+               data = jQuery.makeArray(data);
+
+               if ( type.indexOf("!") >= 0 ) {
+                       type = type.slice(0, -1);
+                       var exclusive = true;
+               }
+
+               // Handle a global trigger
+               if ( !elem ) {
+                       // Only trigger if we've ever bound an event for it
+                       if ( this.global[type] )
+                               jQuery("*").add([window, document]).trigger(type, data);
+
+               // Handle triggering a single element
+               } else {
+                       // don't do events on text and comment nodes
+                       if ( elem.nodeType == 3 || elem.nodeType == 8 )
+                               return undefined;
+
+                       var val, ret, fn = jQuery.isFunction( elem[ type ] || null ),
+                               // Check to see if we need to provide a fake event, or not
+                               event = !data[0] || !data[0].preventDefault;
+
+                       // Pass along a fake event
+                       if ( event ) {
+                               data.unshift({
+                                       type: type,
+                                       target: elem,
+                                       preventDefault: function(){},
+                                       stopPropagation: function(){},
+                                       timeStamp: now()
+                               });
+                               data[0][expando] = true; // no need to fix fake event
+                       }
+
+                       // Enforce the right trigger type
+                       data[0].type = type;
+                       if ( exclusive )
+                               data[0].exclusive = true;
+
+                       // Trigger the event, it is assumed that "handle" is a function
+                       var handle = jQuery.data(elem, "handle");
+                       if ( handle )
+                               val = handle.apply( elem, data );
+
+                       // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
+                       if ( (!fn || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
+                               val = false;
+
+                       // Extra functions don't get the custom event object
+                       if ( event )
+                               data.shift();
+
+                       // Handle triggering of extra function
+                       if ( extra && jQuery.isFunction( extra ) ) {
+                               // call the extra function and tack the current return value on the end for possible inspection
+                               ret = extra.apply( elem, val == null ? data : data.concat( val ) );
+                               // if anything is returned, give it precedence and have it overwrite the previous value
+                               if (ret !== undefined)
+                                       val = ret;
+                       }
+
+                       // Trigger the native events (except for clicks on links)
+                       if ( fn && donative !== false && val !== false && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
+                               this.triggered = true;
+                               try {
+                                       elem[ type ]();
+                               // prevent IE from throwing an error for some hidden elements
+                               } catch (e) {}
+                       }
+
+                       this.triggered = false;
+               }
+
+               return val;
+       },
+
+       handle: function(event) {
+               // returned undefined or false
+               var val, ret, namespace, all, handlers;
+
+               event = arguments[0] = jQuery.event.fix( event || window.event );
+
+               // Namespaced event handlers
+               namespace = event.type.split(".");
+               event.type = namespace[0];
+               namespace = namespace[1];
+               // Cache this now, all = true means, any handler
+               all = !namespace && !event.exclusive;
+
+               handlers = ( jQuery.data(this, "events") || {} )[event.type];
+
+               for ( var j in handlers ) {
+                       var handler = handlers[j];
+
+                       // Filter the functions by class
+                       if ( all || handler.type == namespace ) {
+                               // Pass in a reference to the handler function itself
+                               // So that we can later remove it
+                               event.handler = handler;
+                               event.data = handler.data;
+
+                               ret = handler.apply( this, arguments );
+
+                               if ( val !== false )
+                                       val = ret;
+
+                               if ( ret === false ) {
+                                       event.preventDefault();
+                                       event.stopPropagation();
+                               }
+                       }
+               }
+
+               return val;
+       },
+
+       fix: function(event) {
+               if ( event[expando] == true )
+                       return event;
+
+               // store a copy of the original event object
+               // and "clone" to set read-only properties
+               var originalEvent = event;
+               event = { originalEvent: originalEvent };
+               var props = "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target timeStamp toElement type view wheelDelta which".split(" ");
+               for ( var i=props.length; i; i-- )
+                       event[ props[i] ] = originalEvent[ props[i] ];
+
+               // Mark it as fixed
+               event[expando] = true;
+
+               // add preventDefault and stopPropagation since
+               // they will not work on the clone
+               event.preventDefault = function() {
+                       // if preventDefault exists run it on the original event
+                       if (originalEvent.preventDefault)
+                               originalEvent.preventDefault();
+                       // otherwise set the returnValue property of the original event to false (IE)
+                       originalEvent.returnValue = false;
+               };
+               event.stopPropagation = function() {
+                       // if stopPropagation exists run it on the original event
+                       if (originalEvent.stopPropagation)
+                               originalEvent.stopPropagation();
+                       // otherwise set the cancelBubble property of the original event to true (IE)
+                       originalEvent.cancelBubble = true;
+               };
+
+               // Fix timeStamp
+               event.timeStamp = event.timeStamp || now();
+
+               // Fix target property, if necessary
+               if ( !event.target )
+                       event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
+
+               // check if target is a textnode (safari)
+               if ( event.target.nodeType == 3 )
+                       event.target = event.target.parentNode;
+
+               // Add relatedTarget, if necessary
+               if ( !event.relatedTarget && event.fromElement )
+                       event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
+
+               // Calculate pageX/Y if missing and clientX/Y available
+               if ( event.pageX == null && event.clientX != null ) {
+                       var doc = document.documentElement, body = document.body;
+                       event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
+                       event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
+               }
+
+               // Add which for key events
+               if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
+                       event.which = event.charCode || event.keyCode;
+
+               // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
+               if ( !event.metaKey && event.ctrlKey )
+                       event.metaKey = event.ctrlKey;
+
+               // Add which for click: 1 == left; 2 == middle; 3 == right
+               // Note: button is not normalized, so don't use it
+               if ( !event.which && event.button )
+                       event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
+
+               return event;
+       },
+
+       proxy: function( fn, proxy ){
+               // Set the guid of unique handler to the same of original handler, so it can be removed
+               proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
+               // So proxy can be declared as an argument
+               return proxy;
+       },
+
+       special: {
+               ready: {
+                       setup: function() {
+                               // Make sure the ready event is setup
+                               bindReady();
+                               return;
+                       },
+
+                       teardown: function() { return; }
+               },
+
+               mouseenter: {
+                       setup: function() {
+                               if ( jQuery.browser.msie ) return false;
+                               jQuery(this).bind("mouseover", jQuery.event.special.mouseenter.handler);
+                               return true;
+                       },
+
+                       teardown: function() {
+                               if ( jQuery.browser.msie ) return false;
+                               jQuery(this).unbind("mouseover", jQuery.event.special.mouseenter.handler);
+                               return true;
+                       },
+
+                       handler: function(event) {
+                               // If we actually just moused on to a sub-element, ignore it
+                               if ( withinElement(event, this) ) return true;
+                               // Execute the right handlers by setting the event type to mouseenter
+                               event.type = "mouseenter";
+                               return jQuery.event.handle.apply(this, arguments);
+                       }
+               },
+
+               mouseleave: {
+                       setup: function() {
+                               if ( jQuery.browser.msie ) return false;
+                               jQuery(this).bind("mouseout", jQuery.event.special.mouseleave.handler);
+                               return true;
+                       },
+
+                       teardown: function() {
+                               if ( jQuery.browser.msie ) return false;
+                               jQuery(this).unbind("mouseout", jQuery.event.special.mouseleave.handler);
+                               return true;
+                       },
+
+                       handler: function(event) {
+                               // If we actually just moused on to a sub-element, ignore it
+                               if ( withinElement(event, this) ) return true;
+                               // Execute the right handlers by setting the event type to mouseleave
+                               event.type = "mouseleave";
+                               return jQuery.event.handle.apply(this, arguments);
+                       }
+               }
+       }
+};
+
+jQuery.fn.extend({
+       bind: function( type, data, fn ) {
+               return type == "unload" ? this.one(type, data, fn) : this.each(function(){
+                       jQuery.event.add( this, type, fn || data, fn && data );
+               });
+       },
+
+       one: function( type, data, fn ) {
+               var one = jQuery.event.proxy( fn || data, function(event) {
+                       jQuery(this).unbind(event, one);
+                       return (fn || data).apply( this, arguments );
+               });
+               return this.each(function(){
+                       jQuery.event.add( this, type, one, fn && data);
+               });
+       },
+
+       unbind: function( type, fn ) {
+               return this.each(function(){
+                       jQuery.event.remove( this, type, fn );
+               });
+       },
+
+       trigger: function( type, data, fn ) {
+               return this.each(function(){
+                       jQuery.event.trigger( type, data, this, true, fn );
+               });
+       },
+
+       triggerHandler: function( type, data, fn ) {
+               return this[0] && jQuery.event.trigger( type, data, this[0], false, fn );
+       },
+
+       toggle: function( fn ) {
+               // Save reference to arguments for access in closure
+               var args = arguments, i = 1;
+
+               // link all the functions, so any of them can unbind this click handler
+               while( i < args.length )
+                       jQuery.event.proxy( fn, args[i++] );
+
+               return this.click( jQuery.event.proxy( fn, function(event) {
+                       // Figure out which function to execute
+                       this.lastToggle = ( this.lastToggle || 0 ) % i;
+
+                       // Make sure that clicks stop
+                       event.preventDefault();
+
+                       // and execute the function
+                       return args[ this.lastToggle++ ].apply( this, arguments ) || false;
+               }));
+       },
+
+       hover: function(fnOver, fnOut) {
+               return this.bind('mouseenter', fnOver).bind('mouseleave', fnOut);
+       },
+
+       ready: function(fn) {
+               // Attach the listeners
+               bindReady();
+
+               // If the DOM is already ready
+               if ( jQuery.isReady )
+                       // Execute the function immediately
+                       fn.call( document, jQuery );
+
+               // Otherwise, remember the function for later
+               else
+                       // Add the function to the wait list
+                       jQuery.readyList.push( function() { return fn.call(this, jQuery); } );
+
+               return this;
+       }
+});
+
+jQuery.extend({
+       isReady: false,
+       readyList: [],
+       // Handle when the DOM is ready
+       ready: function() {
+               // Make sure that the DOM is not already loaded
+               if ( !jQuery.isReady ) {
+                       // Remember that the DOM is ready
+                       jQuery.isReady = true;
+
+                       // If there are functions bound, to execute
+                       if ( jQuery.readyList ) {
+                               // Execute all of them
+                               jQuery.each( jQuery.readyList, function(){
+                                       this.call( document );
+                               });
+
+                               // Reset the list of functions
+                               jQuery.readyList = null;
+                       }
+
+                       // Trigger any bound ready events
+                       jQuery(document).triggerHandler("ready");
+               }
+       }
+});
+
+var readyBound = false;
+
+function bindReady(){
+       if ( readyBound ) return;
+       readyBound = true;
+
+       // Mozilla, Opera (see further below for it) and webkit nightlies currently support this event
+       if ( document.addEventListener && !jQuery.browser.opera)
+               // Use the handy event callback
+               document.addEventListener( "DOMContentLoaded", jQuery.ready, false );
+
+       // If IE is used and is not in a frame
+       // Continually check to see if the document is ready
+       if ( jQuery.browser.msie && window == top ) (function(){
+               if (jQuery.isReady) return;
+               try {
+                       // If IE is used, use the trick by Diego Perini
+                       // http://javascript.nwbox.com/IEContentLoaded/
+                       document.documentElement.doScroll("left");
+               } catch( error ) {
+                       setTimeout( arguments.callee, 0 );
+                       return;
+               }
+               // and execute any waiting functions
+               jQuery.ready();
+       })();
+
+       if ( jQuery.browser.opera )
+               document.addEventListener( "DOMContentLoaded", function () {
+                       if (jQuery.isReady) return;
+                       for (var i = 0; i < document.styleSheets.length; i++)
+                               if (document.styleSheets[i].disabled) {
+                                       setTimeout( arguments.callee, 0 );
+                                       return;
+                               }
+                       // and execute any waiting functions
+                       jQuery.ready();
+               }, false);
+
+       if ( jQuery.browser.safari ) {
+               var numStyles;
+               (function(){
+                       if (jQuery.isReady) return;
+                       if ( document.readyState != "loaded" && document.readyState != "complete" ) {
+                               setTimeout( arguments.callee, 0 );
+                               return;
+                       }
+                       if ( numStyles === undefined )
+                               numStyles = jQuery("style, link[rel=stylesheet]").length;
+                       if ( document.styleSheets.length != numStyles ) {
+                               setTimeout( arguments.callee, 0 );
+                               return;
+                       }
+                       // and execute any waiting functions
+                       jQuery.ready();
+               })();
+       }
+
+       // A fallback to window.onload, that will always work
+       jQuery.event.add( window, "load", jQuery.ready );
+}
+
+jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
+       "mousedown,mouseup,mousemove,mouseover,mouseout,change,select," +
+       "submit,keydown,keypress,keyup,error").split(","), function(i, name){
+
+       // Handle event binding
+       jQuery.fn[name] = function(fn){
+               return fn ? this.bind(name, fn) : this.trigger(name);
+       };
+});
+
+// Checks if an event happened on an element within another element
+// Used in jQuery.event.special.mouseenter and mouseleave handlers
+var withinElement = function(event, elem) {
+       // Check if mouse(over|out) are still within the same parent element
+       var parent = event.relatedTarget;
+       // Traverse up the tree
+       while ( parent && parent != elem ) try { parent = parent.parentNode; } catch(error) { parent = elem; }
+       // Return true if we actually just moused on to a sub-element
+       return parent == elem;
+};
+
+// Prevent memory leaks in IE
+// And prevent errors on refresh with events like mouseover in other browsers
+// Window isn't included so as not to unbind existing unload events
+jQuery(window).bind("unload", function() {
+       jQuery("*").add(document).unbind();
+});
+jQuery.fn.extend({
+       // Keep a copy of the old load
+       _load: jQuery.fn.load,
+
+       load: function( url, params, callback ) {
+               if ( typeof url != 'string' )
+                       return this._load( url );
+
+               var off = url.indexOf(" ");
+               if ( off >= 0 ) {
+                       var selector = url.slice(off, url.length);
+                       url = url.slice(0, off);
+               }
+
+               callback = callback || function(){};
+
+               // Default to a GET request
+               var type = "GET";
+
+               // If the second parameter was provided
+               if ( params )
+                       // If it's a function
+                       if ( jQuery.isFunction( params ) ) {
+                               // We assume that it's the callback
+                               callback = params;
+                               params = null;
+
+                       // Otherwise, build a param string
+                       } else {
+                               params = jQuery.param( params );
+                               type = "POST";
+                       }
+
+               var self = this;
+
+               // Request the remote document
+               jQuery.ajax({
+                       url: url,
+                       type: type,
+                       dataType: "html",
+                       data: params,
+                       complete: function(res, status){
+                               // If successful, inject the HTML into all the matched elements
+                               if ( status == "success" || status == "notmodified" )
+                                       // See if a selector was specified
+                                       self.html( selector ?
+                                               // Create a dummy div to hold the results
+                                               jQuery("<div/>")
+                                                       // inject the contents of the document in, removing the scripts
+                                                       // to avoid any 'Permission Denied' errors in IE
+                                                       .append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
+
+                                                       // Locate the specified elements
+                                                       .find(selector) :
+
+                                               // If not, just inject the full result
+                                               res.responseText );
+
+                               self.each( callback, [res.responseText, status, res] );
+                       }
+               });
+               return this;
+       },
+
+       serialize: function() {
+               return jQuery.param(this.serializeArray());
+       },
+       serializeArray: function() {
+               return this.map(function(){
+                       return jQuery.nodeName(this, "form") ?
+                               jQuery.makeArray(this.elements) : this;
+               })
+               .filter(function(){
+                       return this.name && !this.disabled &&
+                               (this.checked || /select|textarea/i.test(this.nodeName) ||
+                                       /text|hidden|password/i.test(this.type));
+               })
+               .map(function(i, elem){
+                       var val = jQuery(this).val();
+                       return val == null ? null :
+                               val.constructor == Array ?
+                                       jQuery.map( val, function(val, i){
+                                               return {name: elem.name, value: val};
+                                       }) :
+                                       {name: elem.name, value: val};
+               }).get();
+       }
+});
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
+       jQuery.fn[o] = function(f){
+               return this.bind(o, f);
+       };
+});
+
+var jsc = now();
+
+jQuery.extend({
+       get: function( url, data, callback, type ) {
+               // shift arguments if data argument was ommited
+               if ( jQuery.isFunction( data ) ) {
+                       callback = data;
+                       data = null;
+               }
+
+               return jQuery.ajax({
+                       type: "GET",
+                       url: url,
+                       data: data,
+                       success: callback,
+                       dataType: type
+               });
+       },
+
+       getScript: function( url, callback ) {
+               return jQuery.get(url, null, callback, "script");
+       },
+
+       getJSON: function( url, data, callback ) {
+               return jQuery.get(url, data, callback, "json");
+       },
+
+       post: function( url, data, callback, type ) {
+               if ( jQuery.isFunction( data ) ) {
+                       callback = data;
+                       data = {};
+               }
+
+               return jQuery.ajax({
+                       type: "POST",
+                       url: url,
+                       data: data,
+                       success: callback,
+                       dataType: type
+               });
+       },
+
+       ajaxSetup: function( settings ) {
+               jQuery.extend( jQuery.ajaxSettings, settings );
+       },
+
+       ajaxSettings: {
+               url: location.href,
+               global: true,
+               type: "GET",
+               timeout: 0,
+               contentType: "application/x-www-form-urlencoded",
+               processData: true,
+               async: true,
+               data: null,
+               username: null,
+               password: null,
+               accepts: {
+                       xml: "application/xml, text/xml",
+                       html: "text/html",
+                       script: "text/javascript, application/javascript",
+                       json: "application/json, text/javascript",
+                       text: "text/plain",
+                       _default: "*/*"
+               }
+       },
+
+       // Last-Modified header cache for next request
+       lastModified: {},
+
+       ajax: function( s ) {
+               // Extend the settings, but re-extend 's' so that it can be
+               // checked again later (in the test suite, specifically)
+               s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
+
+               var jsonp, jsre = /=\?(&|$)/g, status, data,
+                       type = s.type.toUpperCase();
+
+               // convert data if not already a string
+               if ( s.data && s.processData && typeof s.data != "string" )
+                       s.data = jQuery.param(s.data);
+
+               // Handle JSONP Parameter Callbacks
+               if ( s.dataType == "jsonp" ) {
+                       if ( type == "GET" ) {
+                               if ( !s.url.match(jsre) )
+                                       s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
+                       } else if ( !s.data || !s.data.match(jsre) )
+                               s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
+                       s.dataType = "json";
+               }
+
+               // Build temporary JSONP function
+               if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
+                       jsonp = "jsonp" + jsc++;
+
+                       // Replace the =? sequence both in the query string and the data
+                       if ( s.data )
+                               s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
+                       s.url = s.url.replace(jsre, "=" + jsonp + "$1");
+
+                       // We need to make sure
+                       // that a JSONP style response is executed properly
+                       s.dataType = "script";
+
+                       // Handle JSONP-style loading
+                       window[ jsonp ] = function(tmp){
+                               data = tmp;
+                               success();
+                               complete();
+                               // Garbage collect
+                               window[ jsonp ] = undefined;
+                               try{ delete window[ jsonp ]; } catch(e){}
+                               if ( head )
+                                       head.removeChild( script );
+                       };
+               }
+
+               if ( s.dataType == "script" && s.cache == null )
+                       s.cache = false;
+
+               if ( s.cache === false && type == "GET" ) {
+                       var ts = now();
+                       // try replacing _= if it is there
+                       var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
+                       // if nothing was replaced, add timestamp to the end
+                       s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
+               }
+
+               // If data is available, append data to url for get requests
+               if ( s.data && type == "GET" ) {
+                       s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
+
+                       // IE likes to send both get and post data, prevent this
+                       s.data = null;
+               }
+
+               // Watch for a new set of requests
+               if ( s.global && ! jQuery.active++ )
+                       jQuery.event.trigger( "ajaxStart" );
+
+               // Matches an absolute URL, and saves the domain
+               var remote = /^(?:\w+:)?\/\/([^\/?#]+)/;
+
+               // If we're requesting a remote document
+               // and trying to load JSON or Script with a GET
+               if ( s.dataType == "script" && type == "GET"
+                               && remote.test(s.url) && remote.exec(s.url)[1] != location.host ){
+                       var head = document.getElementsByTagName("head")[0];
+                       var script = document.createElement("script");
+                       script.src = s.url;
+                       if (s.scriptCharset)
+                               script.charset = s.scriptCharset;
+
+                       // Handle Script loading
+                       if ( !jsonp ) {
+                               var done = false;
+
+                               // Attach handlers for all browsers
+                               script.onload = script.onreadystatechange = function(){
+                                       if ( !done && (!this.readyState ||
+                                                       this.readyState == "loaded" || this.readyState == "complete") ) {
+                                               done = true;
+                                               success();
+                                               complete();
+                                               head.removeChild( script );
+                                       }
+                               };
+                       }
+
+                       head.appendChild(script);
+
+                       // We handle everything using the script element injection
+                       return undefined;
+               }
+
+               var requestDone = false;
+
+               // Create the request object; Microsoft failed to properly
+               // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
+               var xhr = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
+
+               // Open the socket
+               // Passing null username, generates a login popup on Opera (#2865)
+               if( s.username )
+                       xhr.open(type, s.url, s.async, s.username, s.password);
+               else
+                       xhr.open(type, s.url, s.async);
+
+               // Need an extra try/catch for cross domain requests in Firefox 3
+               try {
+                       // Set the correct header, if data is being sent
+                       if ( s.data )
+                               xhr.setRequestHeader("Content-Type", s.contentType);
+
+                       // Set the If-Modified-Since header, if ifModified mode.
+                       if ( s.ifModified )
+                               xhr.setRequestHeader("If-Modified-Since",
+                                       jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
+
+                       // Set header so the called script knows that it's an XMLHttpRequest
+                       xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+
+                       // Set the Accepts header for the server, depending on the dataType
+                       xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
+                               s.accepts[ s.dataType ] + ", */*" :
+                               s.accepts._default );
+               } catch(e){}
+
+               // Allow custom headers/mimetypes
+               if ( s.beforeSend && s.beforeSend(xhr, s) === false ) {
+                       // cleanup active request counter
+                       s.global && jQuery.active--;
+                       // close opended socket
+                       xhr.abort();
+                       return false;
+               }
+
+               if ( s.global )
+                       jQuery.event.trigger("ajaxSend", [xhr, s]);
+
+               // Wait for a response to come back
+               var onreadystatechange = function(isTimeout){
+                       // The transfer is complete and the data is available, or the request timed out
+                       if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) {
+                               requestDone = true;
+
+                               // clear poll interval
+                               if (ival) {
+                                       clearInterval(ival);
+                                       ival = null;
+                               }
+
+                               status = isTimeout == "timeout" && "timeout" ||
+                                       !jQuery.httpSuccess( xhr ) && "error" ||
+                                       s.ifModified && jQuery.httpNotModified( xhr, s.url ) && "notmodified" ||
+                                       "success";
+
+                               if ( status == "success" ) {
+                                       // Watch for, and catch, XML document parse errors
+                                       try {
+                                               // process the data (runs the xml through httpData regardless of callback)
+                                               data = jQuery.httpData( xhr, s.dataType, s.dataFilter );
+                                       } catch(e) {
+                                               status = "parsererror";
+                                       }
+                               }
+
+                               // Make sure that the request was successful or notmodified
+                               if ( status == "success" ) {
+                                       // Cache Last-Modified header, if ifModified mode.
+                                       var modRes;
+                                       try {
+                                               modRes = xhr.getResponseHeader("Last-Modified");
+                                       } catch(e) {} // swallow exception thrown by FF if header is not available
+
+                                       if ( s.ifModified && modRes )
+                                               jQuery.lastModified[s.url] = modRes;
+
+                                       // JSONP handles its own success callback
+                                       if ( !jsonp )
+                                               success();
+                               } else
+                                       jQuery.handleError(s, xhr, status);
+
+                               // Fire the complete handlers
+                               complete();
+
+                               // Stop memory leaks
+                               if ( s.async )
+                                       xhr = null;
+                       }
+               };
+
+               if ( s.async ) {
+                       // don't attach the handler to the request, just poll it instead
+                       var ival = setInterval(onreadystatechange, 13);
+
+                       // Timeout checker
+                       if ( s.timeout > 0 )
+                               setTimeout(function(){
+                                       // Check to see if the request is still happening
+                                       if ( xhr ) {
+                                               // Cancel the request
+                                               xhr.abort();
+
+                                               if( !requestDone )
+                                                       onreadystatechange( "timeout" );
+                                       }
+                               }, s.timeout);
+               }
+
+               // Send the data
+               try {
+                       xhr.send(s.data);
+               } catch(e) {
+                       jQuery.handleError(s, xhr, null, e);
+               }
+
+               // firefox 1.5 doesn't fire statechange for sync requests
+               if ( !s.async )
+                       onreadystatechange();
+
+               function success(){
+                       // If a local callback was specified, fire it and pass it the data
+                       if ( s.success )
+                               s.success( data, status );
+
+                       // Fire the global callback
+                       if ( s.global )
+                               jQuery.event.trigger( "ajaxSuccess", [xhr, s] );
+               }
+
+               function complete(){
+                       // Process result
+                       if ( s.complete )
+                               s.complete(xhr, status);
+
+                       // The request was completed
+                       if ( s.global )
+                               jQuery.event.trigger( "ajaxComplete", [xhr, s] );
+
+                       // Handle the global AJAX counter
+                       if ( s.global && ! --jQuery.active )
+                               jQuery.event.trigger( "ajaxStop" );
+               }
+
+               // return XMLHttpRequest to allow aborting the request etc.
+               return xhr;
+       },
+
+       handleError: function( s, xhr, status, e ) {
+               // If a local callback was specified, fire it
+               if ( s.error ) s.error( xhr, status, e );
+
+               // Fire the global callback
+               if ( s.global )
+                       jQuery.event.trigger( "ajaxError", [xhr, s, e] );
+       },
+
+       // Counter for holding the number of active queries
+       active: 0,
+
+       // Determines if an XMLHttpRequest was successful or not
+       httpSuccess: function( xhr ) {
+               try {
+                       // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
+                       return !xhr.status && location.protocol == "file:" ||
+                               ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223 ||
+                               jQuery.browser.safari && xhr.status == undefined;
+               } catch(e){}
+               return false;
+       },
+
+       // Determines if an XMLHttpRequest returns NotModified
+       httpNotModified: function( xhr, url ) {
+               try {
+                       var xhrRes = xhr.getResponseHeader("Last-Modified");
+
+                       // Firefox always returns 200. check Last-Modified date
+                       return xhr.status == 304 || xhrRes == jQuery.lastModified[url] ||
+                               jQuery.browser.safari && xhr.status == undefined;
+               } catch(e){}
+               return false;
+       },
+
+       httpData: function( xhr, type, filter ) {
+               var ct = xhr.getResponseHeader("content-type"),
+                       xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0,
+                       data = xml ? xhr.responseXML : xhr.responseText;
+
+               if ( xml && data.documentElement.tagName == "parsererror" )
+                       throw "parsererror";
+                       
+               // Allow a pre-filtering function to sanitize the response
+               if( filter )
+                       data = filter( data, type );
+
+               // If the type is "script", eval it in global context
+               if ( type == "script" )
+                       jQuery.globalEval( data );
+
+               // Get the JavaScript object, if JSON is used.
+               if ( type == "json" )
+                       data = eval("(" + data + ")");
+
+               return data;
+       },
+
+       // Serialize an array of form elements or a set of
+       // key/values into a query string
+       param: function( a ) {
+               var s = [];
+
+               // If an array was passed in, assume that it is an array
+               // of form elements
+               if ( a.constructor == Array || a.jquery )
+                       // Serialize the form elements
+                       jQuery.each( a, function(){
+                               s.push( encodeURIComponent(this.name) + "=" + encodeURIComponent( this.value ) );
+                       });
+
+               // Otherwise, assume that it's an object of key/value pairs
+               else
+                       // Serialize the key/values
+                       for ( var j in a )
+                               // If the value is an array then the key names need to be repeated
+                               if ( a[j] && a[j].constructor == Array )
+                                       jQuery.each( a[j], function(){
+                                               s.push( encodeURIComponent(j) + "=" + encodeURIComponent( this ) );
+                                       });
+                               else
+                                       s.push( encodeURIComponent(j) + "=" + encodeURIComponent( jQuery.isFunction(a[j]) ? a[j]() : a[j] ) );
+
+               // Return the resulting serialization
+               return s.join("&").replace(/%20/g, "+");
+       }
+
+});
+jQuery.fn.extend({
+       show: function(speed,callback){
+               return speed ?
+                       this.animate({
+                               height: "show", width: "show", opacity: "show"
+                       }, speed, callback) :
+
+                       this.filter(":hidden").each(function(){
+                               this.style.display = this.oldblock || "";
+                               if ( jQuery.css(this,"display") == "none" ) {
+                                       var elem = jQuery("<" + this.tagName + " />").appendTo("body");
+                                       this.style.display = elem.css("display");
+                                       // handle an edge condition where css is - div { display:none; } or similar
+                                       if (this.style.display == "none")
+                                               this.style.display = "block";
+                                       elem.remove();
+                               }
+                       }).end();
+       },
+
+       hide: function(speed,callback){
+               return speed ?
+                       this.animate({
+                               height: "hide", width: "hide", opacity: "hide"
+                       }, speed, callback) :
+
+                       this.filter(":visible").each(function(){
+                               this.oldblock = this.oldblock || jQuery.css(this,"display");
+                               this.style.display = "none";
+                       }).end();
+       },
+
+       // Save the old toggle function
+       _toggle: jQuery.fn.toggle,
+
+       toggle: function( fn, fn2 ){
+               return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
+                       this._toggle.apply( this, arguments ) :
+                       fn ?
+                               this.animate({
+                                       height: "toggle", width: "toggle", opacity: "toggle"
+                               }, fn, fn2) :
+                               this.each(function(){
+                                       jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
+                               });
+       },
+
+       slideDown: function(speed,callback){
+               return this.animate({height: "show"}, speed, callback);
+       },
+
+       slideUp: function(speed,callback){
+               return this.animate({height: "hide"}, speed, callback);
+       },
+
+       slideToggle: function(speed, callback){
+               return this.animate({height: "toggle"}, speed, callback);
+       },
+
+       fadeIn: function(speed, callback){
+               return this.animate({opacity: "show"}, speed, callback);
+       },
+
+       fadeOut: function(speed, callback){
+               return this.animate({opacity: "hide"}, speed, callback);
+       },
+
+       fadeTo: function(speed,to,callback){
+               return this.animate({opacity: to}, speed, callback);
+       },
+
+       animate: function( prop, speed, easing, callback ) {
+               var optall = jQuery.speed(speed, easing, callback);
+
+               return this[ optall.queue === false ? "each" : "queue" ](function(){
+                       if ( this.nodeType != 1)
+                               return false;
+
+                       var opt = jQuery.extend({}, optall), p,
+                               hidden = jQuery(this).is(":hidden"), self = this;
+
+                       for ( p in prop ) {
+                               if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
+                                       return opt.complete.call(this);
+
+                               if ( p == "height" || p == "width" ) {
+                                       // Store display property
+                                       opt.display = jQuery.css(this, "display");
+
+                                       // Make sure that nothing sneaks out
+                                       opt.overflow = this.style.overflow;
+                               }
+                       }
+
+                       if ( opt.overflow != null )
+                               this.style.overflow = "hidden";
+
+                       opt.curAnim = jQuery.extend({}, prop);
+
+                       jQuery.each( prop, function(name, val){
+                               var e = new jQuery.fx( self, opt, name );
+
+                               if ( /toggle|show|hide/.test(val) )
+                                       e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
+                               else {
+                                       var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
+                                               start = e.cur(true) || 0;
+
+                                       if ( parts ) {
+                                               var end = parseFloat(parts[2]),
+                                                       unit = parts[3] || "px";
+
+                                               // We need to compute starting value
+                                               if ( unit != "px" ) {
+                                                       self.style[ name ] = (end || 1) + unit;
+                                                       start = ((end || 1) / e.cur(true)) * start;
+                                                       self.style[ name ] = start + unit;
+                                               }
+
+                                               // If a +=/-= token was provided, we're doing a relative animation
+                                               if ( parts[1] )
+                                                       end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
+
+                                               e.custom( start, end, unit );
+                                       } else
+                                               e.custom( start, val, "" );
+                               }
+                       });
+
+                       // For JS strict compliance
+                       return true;
+               });
+       },
+
+       queue: function(type, fn){
+               if ( jQuery.isFunction(type) || ( type && type.constructor == Array )) {
+                       fn = type;
+                       type = "fx";
+               }
+
+               if ( !type || (typeof type == "string" && !fn) )
+                       return queue( this[0], type );
+
+               return this.each(function(){
+                       if ( fn.constructor == Array )
+                               queue(this, type, fn);
+                       else {
+                               queue(this, type).push( fn );
+
+                               if ( queue(this, type).length == 1 )
+                                       fn.call(this);
+                       }
+               });
+       },
+
+       stop: function(clearQueue, gotoEnd){
+               var timers = jQuery.timers;
+
+               if (clearQueue)
+                       this.queue([]);
+
+               this.each(function(){
+                       // go in reverse order so anything added to the queue during the loop is ignored
+                       for ( var i = timers.length - 1; i >= 0; i-- )
+                               if ( timers[i].elem == this ) {
+                                       if (gotoEnd)
+                                               // force the next step to be the last
+                                               timers[i](true);
+                                       timers.splice(i, 1);
+                               }
+               });
+
+               // start the next in the queue if the last step wasn't forced
+               if (!gotoEnd)
+                       this.dequeue();
+
+               return this;
+       }
+
+});
+
+var queue = function( elem, type, array ) {
+       if ( elem ){
+
+               type = type || "fx";
+
+               var q = jQuery.data( elem, type + "queue" );
+
+               if ( !q || array )
+                       q = jQuery.data( elem, type + "queue", jQuery.makeArray(array) );
+
+       }
+       return q;
+};
+
+jQuery.fn.dequeue = function(type){
+       type = type || "fx";
+
+       return this.each(function(){
+               var q = queue(this, type);
+
+               q.shift();
+
+               if ( q.length )
+                       q[0].call( this );
+       });
+};
+
+jQuery.extend({
+
+       speed: function(speed, easing, fn) {
+               var opt = speed && speed.constructor == Object ? speed : {
+                       complete: fn || !fn && easing ||
+                               jQuery.isFunction( speed ) && speed,
+                       duration: speed,
+                       easing: fn && easing || easing && easing.constructor != Function && easing
+               };
+
+               opt.duration = (opt.duration && opt.duration.constructor == Number ?
+                       opt.duration :
+                       jQuery.fx.speeds[opt.duration]) || jQuery.fx.speeds.def;
+
+               // Queueing
+               opt.old = opt.complete;
+               opt.complete = function(){
+                       if ( opt.queue !== false )
+                               jQuery(this).dequeue();
+                       if ( jQuery.isFunction( opt.old ) )
+                               opt.old.call( this );
+               };
+
+               return opt;
+       },
+
+       easing: {
+               linear: function( p, n, firstNum, diff ) {
+                       return firstNum + diff * p;
+               },
+               swing: function( p, n, firstNum, diff ) {
+                       return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
+               }
+       },
+
+       timers: [],
+       timerId: null,
+
+       fx: function( elem, options, prop ){
+               this.options = options;
+               this.elem = elem;
+               this.prop = prop;
+
+               if ( !options.orig )
+                       options.orig = {};
+       }
+
+});
+
+jQuery.fx.prototype = {
+
+       // Simple function for setting a style value
+       update: function(){
+               if ( this.options.step )
+                       this.options.step.call( this.elem, this.now, this );
+
+               (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
+
+               // Set display property to block for height/width animations
+               if ( this.prop == "height" || this.prop == "width" )
+                       this.elem.style.display = "block";
+       },
+
+       // Get the current size
+       cur: function(force){
+               if ( this.elem[this.prop] != null && this.elem.style[this.prop] == null )
+                       return this.elem[ this.prop ];
+
+               var r = parseFloat(jQuery.css(this.elem, this.prop, force));
+               return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
+       },
+
+       // Start an animation from one number to another
+       custom: function(from, to, unit){
+               this.startTime = now();
+               this.start = from;
+               this.end = to;
+               this.unit = unit || this.unit || "px";
+               this.now = this.start;
+               this.pos = this.state = 0;
+               this.update();
+
+               var self = this;
+               function t(gotoEnd){
+                       return self.step(gotoEnd);
+               }
+
+               t.elem = this.elem;
+
+               jQuery.timers.push(t);
+
+               if ( jQuery.timerId == null ) {
+                       jQuery.timerId = setInterval(function(){
+                               var timers = jQuery.timers;
+
+                               for ( var i = 0; i < timers.length; i++ )
+                                       if ( !timers[i]() )
+                                               timers.splice(i--, 1);
+
+                               if ( !timers.length ) {
+                                       clearInterval( jQuery.timerId );
+                                       jQuery.timerId = null;
+                               }
+                       }, 13);
+               }
+       },
+
+       // Simple 'show' function
+       show: function(){
+               // Remember where we started, so that we can go back to it later
+               this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+               this.options.show = true;
+
+               // Begin the animation
+               this.custom(0, this.cur());
+
+               // Make sure that we start at a small width/height to avoid any
+               // flash of content
+               if ( this.prop == "width" || this.prop == "height" )
+                       this.elem.style[this.prop] = "1px";
+
+               // Start by showing the element
+               jQuery(this.elem).show();
+       },
+
+       // Simple 'hide' function
+       hide: function(){
+               // Remember where we started, so that we can go back to it later
+               this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+               this.options.hide = true;
+
+               // Begin the animation
+               this.custom(this.cur(), 0);
+       },
+
+       // Each step of an animation
+       step: function(gotoEnd){
+               var t = now();
+
+               if ( gotoEnd || t > this.options.duration + this.startTime ) {
+                       this.now = this.end;
+                       this.pos = this.state = 1;
+                       this.update();
+
+                       this.options.curAnim[ this.prop ] = true;
+
+                       var done = true;
+                       for ( var i in this.options.curAnim )
+                               if ( this.options.curAnim[i] !== true )
+                                       done = false;
+
+                       if ( done ) {
+                               if ( this.options.display != null ) {
+                                       // Reset the overflow
+                                       this.elem.style.overflow = this.options.overflow;
+
+                                       // Reset the display
+                                       this.elem.style.display = this.options.display;
+                                       if ( jQuery.css(this.elem, "display") == "none" )
+                                               this.elem.style.display = "block";
+                               }
+
+                               // Hide the element if the "hide" operation was done
+                               if ( this.options.hide )
+                                       this.elem.style.display = "none";
+
+                               // Reset the properties, if the item has been hidden or shown
+                               if ( this.options.hide || this.options.show )
+                                       for ( var p in this.options.curAnim )
+                                               jQuery.attr(this.elem.style, p, this.options.orig[p]);
+                       }
+
+                       if ( done )
+                               // Execute the complete function
+                               this.options.complete.call( this.elem );
+
+                       return false;
+               } else {
+                       var n = t - this.startTime;
+                       this.state = n / this.options.duration;
+
+                       // Perform the easing function, defaults to swing
+                       this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
+                       this.now = this.start + ((this.end - this.start) * this.pos);
+
+                       // Perform the next step of the animation
+                       this.update();
+               }
+
+               return true;
+       }
+
+};
+
+jQuery.extend( jQuery.fx, {
+       speeds:{
+               slow: 600,
+               fast: 200,
+               // Default speed
+               def: 400
+       },
+       step: {
+               scrollLeft: function(fx){
+                       fx.elem.scrollLeft = fx.now;
+               },
+
+               scrollTop: function(fx){
+                       fx.elem.scrollTop = fx.now;
+               },
+
+               opacity: function(fx){
+                       jQuery.attr(fx.elem.style, "opacity", fx.now);
+               },
+
+               _default: function(fx){
+                       fx.elem.style[ fx.prop ] = fx.now + fx.unit;
+               }
+       }
+});
+// The Offset Method
+// Originally By Brandon Aaron, part of the Dimension Plugin
+// http://jquery.com/plugins/project/dimensions
+jQuery.fn.offset = function() {
+       var left = 0, top = 0, elem = this[0], results;
+
+       if ( elem ) with ( jQuery.browser ) {
+               var parent       = elem.parentNode,
+                   offsetChild  = elem,
+                   offsetParent = elem.offsetParent,
+                   doc          = elem.ownerDocument,
+                   safari2      = safari && parseInt(version) < 522 && !/adobeair/i.test(userAgent),
+                   css          = jQuery.curCSS,
+                   fixed        = css(elem, "position") == "fixed";
+
+               // Use getBoundingClientRect if available
+               if ( elem.getBoundingClientRect ) {
+                       var box = elem.getBoundingClientRect();
+
+                       // Add the document scroll offsets
+                       add(box.left + Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
+                               box.top  + Math.max(doc.documentElement.scrollTop,  doc.body.scrollTop));
+
+                       // IE adds the HTML element's border, by default it is medium which is 2px
+                       // IE 6 and 7 quirks mode the border width is overwritable by the following css html { border: 0; }
+                       // IE 7 standards mode, the border is always 2px
+                       // This border/offset is typically represented by the clientLeft and clientTop properties
+                       // However, in IE6 and 7 quirks mode the clientLeft and clientTop properties are not updated when overwriting it via CSS
+                       // Therefore this method will be off by 2px in IE while in quirksmode
+                       add( -doc.documentElement.clientLeft, -doc.documentElement.clientTop );
+
+               // Otherwise loop through the offsetParents and parentNodes
+               } else {
+
+                       // Initial element offsets
+                       add( elem.offsetLeft, elem.offsetTop );
+
+                       // Get parent offsets
+                       while ( offsetParent ) {
+                               // Add offsetParent offsets
+                               add( offsetParent.offsetLeft, offsetParent.offsetTop );
+
+                               // Mozilla and Safari > 2 does not include the border on offset parents
+                               // However Mozilla adds the border for table or table cells
+                               if ( mozilla && !/^t(able|d|h)$/i.test(offsetParent.tagName) || safari && !safari2 )
+                                       border( offsetParent );
+
+                               // Add the document scroll offsets if position is fixed on any offsetParent
+                               if ( !fixed && css(offsetParent, "position") == "fixed" )
+                                       fixed = true;
+
+                               // Set offsetChild to previous offsetParent unless it is the body element
+                               offsetChild  = /^body$/i.test(offsetParent.tagName) ? offsetChild : offsetParent;
+                               // Get next offsetParent
+                               offsetParent = offsetParent.offsetParent;
+                       }
+
+                       // Get parent scroll offsets
+                       while ( parent && parent.tagName && !/^body|html$/i.test(parent.tagName) ) {
+                               // Remove parent scroll UNLESS that parent is inline or a table to work around Opera inline/table scrollLeft/Top bug
+                               if ( !/^inline|table.*$/i.test(css(parent, "display")) )
+                                       // Subtract parent scroll offsets
+                                       add( -parent.scrollLeft, -parent.scrollTop );
+
+                               // Mozilla does not add the border for a parent that has overflow != visible
+                               if ( mozilla && css(parent, "overflow") != "visible" )
+                                       border( parent );
+
+                               // Get next parent
+                               parent = parent.parentNode;
+                       }
+
+                       // Safari <= 2 doubles body offsets with a fixed position element/offsetParent or absolutely positioned offsetChild
+                       // Mozilla doubles body offsets with a non-absolutely positioned offsetChild
+                       if ( (safari2 && (fixed || css(offsetChild, "position") == "absolute")) ||
+                               (mozilla && css(offsetChild, "position") != "absolute") )
+                                       add( -doc.body.offsetLeft, -doc.body.offsetTop );
+
+                       // Add the document scroll offsets if position is fixed
+                       if ( fixed )
+                               add(Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
+                                       Math.max(doc.documentElement.scrollTop,  doc.body.scrollTop));
+               }
+
+               // Return an object with top and left properties
+               results = { top: top, left: left };
+       }
+
+       function border(elem) {
+               add( jQuery.curCSS(elem, "borderLeftWidth", true), jQuery.curCSS(elem, "borderTopWidth", true) );
+       }
+
+       function add(l, t) {
+               left += parseInt(l, 10) || 0;
+               top += parseInt(t, 10) || 0;
+       }
+
+       return results;
+};
+
+
+jQuery.fn.extend({
+       position: function() {
+               var left = 0, top = 0, results;
+
+               if ( this[0] ) {
+                       // Get *real* offsetParent
+                       var offsetParent = this.offsetParent(),
+
+                       // Get correct offsets
+                       offset       = this.offset(),
+                       parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset();
+
+                       // Subtract element margins
+                       // note: when an element has margin: auto the offsetLeft and marginLeft 
+                       // are the same in Safari causing offset.left to incorrectly be 0
+                       offset.top  -= num( this, 'marginTop' );
+                       offset.left -= num( this, 'marginLeft' );
+
+                       // Add offsetParent borders
+                       parentOffset.top  += num( offsetParent, 'borderTopWidth' );
+                       parentOffset.left += num( offsetParent, 'borderLeftWidth' );
+
+                       // Subtract the two offsets
+                       results = {
+                               top:  offset.top  - parentOffset.top,
+                               left: offset.left - parentOffset.left
+                       };
+               }
+
+               return results;
+       },
+
+       offsetParent: function() {
+               var offsetParent = this[0].offsetParent;
+               while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') )
+                       offsetParent = offsetParent.offsetParent;
+               return jQuery(offsetParent);
+       }
+});
+
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( ['Left', 'Top'], function(i, name) {
+       var method = 'scroll' + name;
+       
+       jQuery.fn[ method ] = function(val) {
+               if (!this[0]) return;
+
+               return val != undefined ?
+
+                       // Set the scroll offset
+                       this.each(function() {
+                               this == window || this == document ?
+                                       window.scrollTo(
+                                               !i ? val : jQuery(window).scrollLeft(),
+                                                i ? val : jQuery(window).scrollTop()
+                                       ) :
+                                       this[ method ] = val;
+                       }) :
+
+                       // Return the scroll offset
+                       this[0] == window || this[0] == document ?
+                               self[ i ? 'pageYOffset' : 'pageXOffset' ] ||
+                                       jQuery.boxModel && document.documentElement[ method ] ||
+                                       document.body[ method ] :
+                               this[0][ method ];
+       };
+});
+// Create innerHeight, innerWidth, outerHeight and outerWidth methods
+jQuery.each([ "Height", "Width" ], function(i, name){
+
+       var tl = i ? "Left"  : "Top",  // top or left
+               br = i ? "Right" : "Bottom"; // bottom or right
+
+       // innerHeight and innerWidth
+       jQuery.fn["inner" + name] = function(){
+               return this[ name.toLowerCase() ]() +
+                       num(this, "padding" + tl) +
+                       num(this, "padding" + br);
+       };
+
+       // outerHeight and outerWidth
+       jQuery.fn["outer" + name] = function(margin) {
+               return this["inner" + name]() +
+                       num(this, "border" + tl + "Width") +
+                       num(this, "border" + br + "Width") +
+                       (margin ?
+                               num(this, "margin" + tl) + num(this, "margin" + br) : 0);
+       };
+
+});})();
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/jquery-1.2.6.min.js b/forum/modules/template_loader.py/forum/skins/default/media/js/jquery-1.2.6.min.js
new file mode 100644 (file)
index 0000000..82b98e1
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * jQuery 1.2.6 - New Wave Javascript
+ *
+ * Copyright (c) 2008 John Resig (jquery.com)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * $Date: 2008-05-24 14:22:17 -0400 (Sat, 24 May 2008) $
+ * $Rev: 5685 $
+ */
+(function(){var _jQuery=window.jQuery,_$=window.$;var jQuery=window.jQuery=window.$=function(selector,context){return new jQuery.fn.init(selector,context);};var quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/,isSimple=/^.[^:#\[\.]*$/,undefined;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;return this;}if(typeof selector=="string"){var match=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1])selector=jQuery.clean([match[1]],context);else{var elem=document.getElementById(match[3]);if(elem){if(elem.id!=match[3])return jQuery().find(selector);return jQuery(elem);}selector=[];}}else
+return jQuery(context).find(selector);}else if(jQuery.isFunction(selector))return jQuery(document)[jQuery.fn.ready?"ready":"load"](selector);return this.setArray(jQuery.makeArray(selector));},jquery:"1.2.6",size:function(){return this.length;},length:0,get:function(num){return num==undefined?jQuery.makeArray(this):this[num];},pushStack:function(elems){var ret=jQuery(elems);ret.prevObject=this;return ret;},setArray:function(elems){this.length=0;Array.prototype.push.apply(this,elems);return this;},each:function(callback,args){return jQuery.each(this,callback,args);},index:function(elem){var ret=-1;return jQuery.inArray(elem&&elem.jquery?elem[0]:elem,this);},attr:function(name,value,type){var options=name;if(name.constructor==String)if(value===undefined)return this[0]&&jQuery[type||"attr"](this[0],name);else{options={};options[name]=value;}return this.each(function(i){for(name in options)jQuery.attr(type?this.style:this,name,jQuery.prop(this,options[name],type,i,name));});},css:function(key,value){if((key=='width'||key=='height')&&parseFloat(value)<0)value=undefined;return this.attr(key,value,"curCSS");},text:function(text){if(typeof text!="object"&&text!=null)return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(text));var ret="";jQuery.each(text||this,function(){jQuery.each(this.childNodes,function(){if(this.nodeType!=8)ret+=this.nodeType!=1?this.nodeValue:jQuery.fn.text([this]);});});return ret;},wrapAll:function(html){if(this[0])jQuery(html,this[0].ownerDocument).clone().insertBefore(this[0]).map(function(){var elem=this;while(elem.firstChild)elem=elem.firstChild;return elem;}).append(this);return this;},wrapInner:function(html){return this.each(function(){jQuery(this).contents().wrapAll(html);});},wrap:function(html){return this.each(function(){jQuery(this).wrapAll(html);});},append:function(){return this.domManip(arguments,true,false,function(elem){if(this.nodeType==1)this.appendChild(elem);});},prepend:function(){return this.domManip(arguments,true,true,function(elem){if(this.nodeType==1)this.insertBefore(elem,this.firstChild);});},before:function(){return this.domManip(arguments,false,false,function(elem){this.parentNode.insertBefore(elem,this);});},after:function(){return this.domManip(arguments,false,true,function(elem){this.parentNode.insertBefore(elem,this.nextSibling);});},end:function(){return this.prevObject||jQuery([]);},find:function(selector){var elems=jQuery.map(this,function(elem){return jQuery.find(selector,elem);});return this.pushStack(/[^+>] [^+>]/.test(selector)||selector.indexOf("..")>-1?jQuery.unique(elems):elems);},clone:function(events){var ret=this.map(function(){if(jQuery.browser.msie&&!jQuery.isXMLDoc(this)){var clone=this.cloneNode(true),container=document.createElement("div");container.appendChild(clone);return jQuery.clean([container.innerHTML])[0];}else
+return this.cloneNode(true);});var clone=ret.find("*").andSelf().each(function(){if(this[expando]!=undefined)this[expando]=null;});if(events===true)this.find("*").andSelf().each(function(i){if(this.nodeType==3)return;var events=jQuery.data(this,"events");for(var type in events)for(var handler in events[type])jQuery.event.add(clone[i],type,events[type][handler],events[type][handler].data);});return ret;},filter:function(selector){return this.pushStack(jQuery.isFunction(selector)&&jQuery.grep(this,function(elem,i){return selector.call(elem,i);})||jQuery.multiFilter(selector,this));},not:function(selector){if(selector.constructor==String)if(isSimple.test(selector))return this.pushStack(jQuery.multiFilter(selector,this,true));else
+selector=jQuery.multiFilter(selector,this);var isArrayLike=selector.length&&selector[selector.length-1]!==undefined&&!selector.nodeType;return this.filter(function(){return isArrayLike?jQuery.inArray(this,selector)<0:this!=selector;});},add:function(selector){return this.pushStack(jQuery.unique(jQuery.merge(this.get(),typeof selector=='string'?jQuery(selector):jQuery.makeArray(selector))));},is:function(selector){return!!selector&&jQuery.multiFilter(selector,this).length>0;},hasClass:function(selector){return this.is("."+selector);},val:function(value){if(value==undefined){if(this.length){var elem=this[0];if(jQuery.nodeName(elem,"select")){var index=elem.selectedIndex,values=[],options=elem.options,one=elem.type=="select-one";if(index<0)return null;for(var i=one?index:0,max=one?index+1:options.length;i<max;i++){var option=options[i];if(option.selected){value=jQuery.browser.msie&&!option.attributes.value.specified?option.text:option.value;if(one)return value;values.push(value);}}return values;}else
+return(this[0].value||"").replace(/\r/g,"");}return undefined;}if(value.constructor==Number)value+='';return this.each(function(){if(this.nodeType!=1)return;if(value.constructor==Array&&/radio|checkbox/.test(this.type))this.checked=(jQuery.inArray(this.value,value)>=0||jQuery.inArray(this.name,value)>=0);else if(jQuery.nodeName(this,"select")){var values=jQuery.makeArray(value);jQuery("option",this).each(function(){this.selected=(jQuery.inArray(this.value,values)>=0||jQuery.inArray(this.text,values)>=0);});if(!values.length)this.selectedIndex=-1;}else
+this.value=value;});},html:function(value){return value==undefined?(this[0]?this[0].innerHTML:null):this.empty().append(value);},replaceWith:function(value){return this.after(value).remove();},eq:function(i){return this.slice(i,i+1);},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments));},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem);}));},andSelf:function(){return this.add(this.prevObject);},data:function(key,value){var parts=key.split(".");parts[1]=parts[1]?"."+parts[1]:"";if(value===undefined){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data===undefined&&this.length)data=jQuery.data(this[0],key);return data===undefined&&parts[1]?this.data(parts[0]):data;}else
+return this.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){jQuery.data(this,key,value);});},removeData:function(key){return this.each(function(){jQuery.removeData(this,key);});},domManip:function(args,table,reverse,callback){var clone=this.length>1,elems;return this.each(function(){if(!elems){elems=jQuery.clean(args,this.ownerDocument);if(reverse)elems.reverse();}var obj=this;if(table&&jQuery.nodeName(this,"table")&&jQuery.nodeName(elems[0],"tr"))obj=this.getElementsByTagName("tbody")[0]||this.appendChild(this.ownerDocument.createElement("tbody"));var scripts=jQuery([]);jQuery.each(elems,function(){var elem=clone?jQuery(this).clone(true)[0]:this;if(jQuery.nodeName(elem,"script"))scripts=scripts.add(elem);else{if(elem.nodeType==1)scripts=scripts.add(jQuery("script",elem).remove());callback.call(obj,elem);}});scripts.each(evalScript);});}};jQuery.fn.init.prototype=jQuery.fn;function evalScript(i,elem){if(elem.src)jQuery.ajax({url:elem.src,async:false,dataType:"script"});else
+jQuery.globalEval(elem.text||elem.textContent||elem.innerHTML||"");if(elem.parentNode)elem.parentNode.removeChild(elem);}function now(){return+new Date;}jQuery.extend=jQuery.fn.extend=function(){var target=arguments[0]||{},i=1,length=arguments.length,deep=false,options;if(target.constructor==Boolean){deep=target;target=arguments[1]||{};i=2;}if(typeof target!="object"&&typeof target!="function")target={};if(length==i){target=this;--i;}for(;i<length;i++)if((options=arguments[i])!=null)for(var name in options){var src=target[name],copy=options[name];if(target===copy)continue;if(deep&&copy&&typeof copy=="object"&&!copy.nodeType)target[name]=jQuery.extend(deep,src||(copy.length!=null?[]:{}),copy);else if(copy!==undefined)target[name]=copy;}return target;};var expando="jQuery"+now(),uuid=0,windowData={},exclude=/z-?index|font-?weight|opacity|zoom|line-?height/i,defaultView=document.defaultView||{};jQuery.extend({noConflict:function(deep){window.$=_$;if(deep)window.jQuery=_jQuery;return jQuery;},isFunction:function(fn){return!!fn&&typeof fn!="string"&&!fn.nodeName&&fn.constructor!=Array&&/^[\s[]?function/.test(fn+"");},isXMLDoc:function(elem){return elem.documentElement&&!elem.body||elem.tagName&&elem.ownerDocument&&!elem.ownerDocument.body;},globalEval:function(data){data=jQuery.trim(data);if(data){var head=document.getElementsByTagName("head")[0]||document.documentElement,script=document.createElement("script");script.type="text/javascript";if(jQuery.browser.msie)script.text=data;else
+script.appendChild(document.createTextNode(data));head.insertBefore(script,head.firstChild);head.removeChild(script);}},nodeName:function(elem,name){return elem.nodeName&&elem.nodeName.toUpperCase()==name.toUpperCase();},cache:{},data:function(elem,name,data){elem=elem==window?windowData:elem;var id=elem[expando];if(!id)id=elem[expando]=++uuid;if(name&&!jQuery.cache[id])jQuery.cache[id]={};if(data!==undefined)jQuery.cache[id][name]=data;return name?jQuery.cache[id][name]:id;},removeData:function(elem,name){elem=elem==window?windowData:elem;var id=elem[expando];if(name){if(jQuery.cache[id]){delete jQuery.cache[id][name];name="";for(name in jQuery.cache[id])break;if(!name)jQuery.removeData(elem);}}else{try{delete elem[expando];}catch(e){if(elem.removeAttribute)elem.removeAttribute(expando);}delete jQuery.cache[id];}},each:function(object,callback,args){var name,i=0,length=object.length;if(args){if(length==undefined){for(name in object)if(callback.apply(object[name],args)===false)break;}else
+for(;i<length;)if(callback.apply(object[i++],args)===false)break;}else{if(length==undefined){for(name in object)if(callback.call(object[name],name,object[name])===false)break;}else
+for(var value=object[0];i<length&&callback.call(value,i,value)!==false;value=object[++i]){}}return object;},prop:function(elem,value,type,i,name){if(jQuery.isFunction(value))value=value.call(elem,i);return value&&value.constructor==Number&&type=="curCSS"&&!exclude.test(name)?value+"px":value;},className:{add:function(elem,classNames){jQuery.each((classNames||"").split(/\s+/),function(i,className){if(elem.nodeType==1&&!jQuery.className.has(elem.className,className))elem.className+=(elem.className?" ":"")+className;});},remove:function(elem,classNames){if(elem.nodeType==1)elem.className=classNames!=undefined?jQuery.grep(elem.className.split(/\s+/),function(className){return!jQuery.className.has(classNames,className);}).join(" "):"";},has:function(elem,className){return jQuery.inArray(className,(elem.className||elem).toString().split(/\s+/))>-1;}},swap:function(elem,options,callback){var old={};for(var name in options){old[name]=elem.style[name];elem.style[name]=options[name];}callback.call(elem);for(var name in options)elem.style[name]=old[name];},css:function(elem,name,force){if(name=="width"||name=="height"){var val,props={position:"absolute",visibility:"hidden",display:"block"},which=name=="width"?["Left","Right"]:["Top","Bottom"];function getWH(){val=name=="width"?elem.offsetWidth:elem.offsetHeight;var padding=0,border=0;jQuery.each(which,function(){padding+=parseFloat(jQuery.curCSS(elem,"padding"+this,true))||0;border+=parseFloat(jQuery.curCSS(elem,"border"+this+"Width",true))||0;});val-=Math.round(padding+border);}if(jQuery(elem).is(":visible"))getWH();else
+jQuery.swap(elem,props,getWH);return Math.max(0,val);}return jQuery.curCSS(elem,name,force);},curCSS:function(elem,name,force){var ret,style=elem.style;function color(elem){if(!jQuery.browser.safari)return false;var ret=defaultView.getComputedStyle(elem,null);return!ret||ret.getPropertyValue("color")=="";}if(name=="opacity"&&jQuery.browser.msie){ret=jQuery.attr(style,"opacity");return ret==""?"1":ret;}if(jQuery.browser.opera&&name=="display"){var save=style.outline;style.outline="0 solid black";style.outline=save;}if(name.match(/float/i))name=styleFloat;if(!force&&style&&style[name])ret=style[name];else if(defaultView.getComputedStyle){if(name.match(/float/i))name="float";name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var computedStyle=defaultView.getComputedStyle(elem,null);if(computedStyle&&!color(elem))ret=computedStyle.getPropertyValue(name);else{var swap=[],stack=[],a=elem,i=0;for(;a&&color(a);a=a.parentNode)stack.unshift(a);for(;i<stack.length;i++)if(color(stack[i])){swap[i]=stack[i].style.display;stack[i].style.display="block";}ret=name=="display"&&swap[stack.length-1]!=null?"none":(computedStyle&&computedStyle.getPropertyValue(name))||"";for(i=0;i<swap.length;i++)if(swap[i]!=null)stack[i].style.display=swap[i];}if(name=="opacity"&&ret=="")ret="1";}else if(elem.currentStyle){var camelCase=name.replace(/\-(\w)/g,function(all,letter){return letter.toUpperCase();});ret=elem.currentStyle[name]||elem.currentStyle[camelCase];if(!/^\d+(px)?$/i.test(ret)&&/^\d/.test(ret)){var left=style.left,rsLeft=elem.runtimeStyle.left;elem.runtimeStyle.left=elem.currentStyle.left;style.left=ret||0;ret=style.pixelLeft+"px";style.left=left;elem.runtimeStyle.left=rsLeft;}}return ret;},clean:function(elems,context){var ret=[];context=context||document;if(typeof context.createElement=='undefined')context=context.ownerDocument||context[0]&&context[0].ownerDocument||document;jQuery.each(elems,function(i,elem){if(!elem)return;if(elem.constructor==Number)elem+='';if(typeof elem=="string"){elem=elem.replace(/(<(\w+)[^>]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+"></"+tag+">";});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("<opt")&&[1,"<select multiple='multiple'>","</select>"]||!tags.indexOf("<leg")&&[1,"<fieldset>","</fieldset>"]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"<table>","</table>"]||!tags.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!tags.indexOf("<td")||!tags.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||!tags.indexOf("<col")&&[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]||jQuery.browser.msie&&[1,"div<div>","</div>"]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--)div=div.lastChild;if(jQuery.browser.msie){var tbody=!tags.indexOf("<table")&&tags.indexOf("<tbody")<0?div.firstChild&&div.firstChild.childNodes:wrap[1]=="<table>"&&tags.indexOf("<tbody")<0?div.childNodes:[];for(var j=tbody.length-1;j>=0;--j)if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length)tbody[j].parentNode.removeChild(tbody[j]);if(/^\s/.test(elem))div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]),div.firstChild);}elem=jQuery.makeArray(div.childNodes);}if(elem.length===0&&(!jQuery.nodeName(elem,"form")&&!jQuery.nodeName(elem,"select")))return;if(elem[0]==undefined||jQuery.nodeName(elem,"form")||elem.options)ret.push(elem);else
+ret=jQuery.merge(ret,elem);});return ret;},attr:function(elem,name,value){if(!elem||elem.nodeType==3||elem.nodeType==8)return undefined;var notxml=!jQuery.isXMLDoc(elem),set=value!==undefined,msie=jQuery.browser.msie;name=notxml&&jQuery.props[name]||name;if(elem.tagName){var special=/href|src|style/.test(name);if(name=="selected"&&jQuery.browser.safari)elem.parentNode.selectedIndex;if(name in elem&&notxml&&!special){if(set){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode)throw"type property can't be changed";elem[name]=value;}if(jQuery.nodeName(elem,"form")&&elem.getAttributeNode(name))return elem.getAttributeNode(name).nodeValue;return elem[name];}if(msie&&notxml&&name=="style")return jQuery.attr(elem.style,"cssText",value);if(set)elem.setAttribute(name,""+value);var attr=msie&&notxml&&special?elem.getAttribute(name,2):elem.getAttribute(name);return attr===null?undefined:attr;}if(msie&&name=="opacity"){if(set){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(value)+''=="NaN"?"":"alpha(opacity="+value*100+")");}return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100)+'':"";}name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase();});if(set)elem[name]=value;return elem[name];},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"");},makeArray:function(array){var ret=[];if(array!=null){var i=array.length;if(i==null||array.split||array.setInterval||array.call)ret[0]=array;else
+while(i)ret[--i]=array[i];}return ret;},inArray:function(elem,array){for(var i=0,length=array.length;i<length;i++)if(array[i]===elem)return i;return-1;},merge:function(first,second){var i=0,elem,pos=first.length;if(jQuery.browser.msie){while(elem=second[i++])if(elem.nodeType!=8)first[pos++]=elem;}else
+while(elem=second[i++])first[pos++]=elem;return first;},unique:function(array){var ret=[],done={};try{for(var i=0,length=array.length;i<length;i++){var id=jQuery.data(array[i]);if(!done[id]){done[id]=true;ret.push(array[i]);}}}catch(e){ret=array;}return ret;},grep:function(elems,callback,inv){var ret=[];for(var i=0,length=elems.length;i<length;i++)if(!inv!=!callback(elems[i],i))ret.push(elems[i]);return ret;},map:function(elems,callback){var ret=[];for(var i=0,length=elems.length;i<length;i++){var value=callback(elems[i],i);if(value!=null)ret[ret.length]=value;}return ret.concat.apply([],ret);}});var userAgent=navigator.userAgent.toLowerCase();jQuery.browser={version:(userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[])[1],safari:/webkit/.test(userAgent),opera:/opera/.test(userAgent),msie:/msie/.test(userAgent)&&!/opera/.test(userAgent),mozilla:/mozilla/.test(userAgent)&&!/(compatible|webkit)/.test(userAgent)};var styleFloat=jQuery.browser.msie?"styleFloat":"cssFloat";jQuery.extend({boxModel:!jQuery.browser.msie||document.compatMode=="CSS1Compat",props:{"for":"htmlFor","class":"className","float":styleFloat,cssFloat:styleFloat,styleFloat:styleFloat,readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing"}});jQuery.each({parent:function(elem){return elem.parentNode;},parents:function(elem){return jQuery.dir(elem,"parentNode");},next:function(elem){return jQuery.nth(elem,2,"nextSibling");},prev:function(elem){return jQuery.nth(elem,2,"previousSibling");},nextAll:function(elem){return jQuery.dir(elem,"nextSibling");},prevAll:function(elem){return jQuery.dir(elem,"previousSibling");},siblings:function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},children:function(elem){return jQuery.sibling(elem.firstChild);},contents:function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}},function(name,fn){jQuery.fn[name]=function(selector){var ret=jQuery.map(this,fn);if(selector&&typeof selector=="string")ret=jQuery.multiFilter(selector,ret);return this.pushStack(jQuery.unique(ret));};});jQuery.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(name,original){jQuery.fn[name]=function(){var args=arguments;return this.each(function(){for(var i=0,length=args.length;i<length;i++)jQuery(args[i])[original](this);});};});jQuery.each({removeAttr:function(name){jQuery.attr(this,name,"");if(this.nodeType==1)this.removeAttribute(name);},addClass:function(classNames){jQuery.className.add(this,classNames);},removeClass:function(classNames){jQuery.className.remove(this,classNames);},toggleClass:function(classNames){jQuery.className[jQuery.className.has(this,classNames)?"remove":"add"](this,classNames);},remove:function(selector){if(!selector||jQuery.filter(selector,[this]).r.length){jQuery("*",this).add(this).each(function(){jQuery.event.remove(this);jQuery.removeData(this);});if(this.parentNode)this.parentNode.removeChild(this);}},empty:function(){jQuery(">*",this).remove();while(this.firstChild)this.removeChild(this.firstChild);}},function(name,fn){jQuery.fn[name]=function(){return this.each(fn,arguments);};});jQuery.each(["Height","Width"],function(i,name){var type=name.toLowerCase();jQuery.fn[type]=function(size){return this[0]==window?jQuery.browser.opera&&document.body["client"+name]||jQuery.browser.safari&&window["inner"+name]||document.compatMode=="CSS1Compat"&&document.documentElement["client"+name]||document.body["client"+name]:this[0]==document?Math.max(Math.max(document.body["scroll"+name],document.documentElement["scroll"+name]),Math.max(document.body["offset"+name],document.documentElement["offset"+name])):size==undefined?(this.length?jQuery.css(this[0],type):null):this.css(type,size.constructor==String?size:size+"px");};});function num(elem,prop){return elem[0]&&parseInt(jQuery.curCSS(elem[0],prop,true),10)||0;}var chars=jQuery.browser.safari&&parseInt(jQuery.browser.version)<417?"(?:[\\w*_-]|\\\\.)":"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",quickChild=new RegExp("^>\\s*("+chars+"+)"),quickID=new RegExp("^("+chars+"+)(#)("+chars+"+)"),quickClass=new RegExp("^([#.]?)("+chars+"*)");jQuery.extend({expr:{"":function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},"#":function(a,i,m){return a.getAttribute("id")==m[2];},":":{lt:function(a,i,m){return i<m[3]-0;},gt:function(a,i,m){return i>m[3]-0;},nth:function(a,i,m){return m[3]-0==i;},eq:function(a,i,m){return m[3]-0==i;},first:function(a,i){return i==0;},last:function(a,i,m,r){return i==r.length-1;},even:function(a,i){return i%2==0;},odd:function(a,i){return i%2;},"first-child":function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},"last-child":function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},"only-child":function(a){return!jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},parent:function(a){return a.firstChild;},empty:function(a){return!a.firstChild;},contains:function(a,i,m){return(a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},visible:function(a){return"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},hidden:function(a){return"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},enabled:function(a){return!a.disabled;},disabled:function(a){return a.disabled;},checked:function(a){return a.checked;},selected:function(a){return a.selected||jQuery.attr(a,"selected");},text:function(a){return"text"==a.type;},radio:function(a){return"radio"==a.type;},checkbox:function(a){return"checkbox"==a.type;},file:function(a){return"file"==a.type;},password:function(a){return"password"==a.type;},submit:function(a){return"submit"==a.type;},image:function(a){return"image"==a.type;},reset:function(a){return"reset"==a.type;},button:function(a){return"button"==a.type||jQuery.nodeName(a,"button");},input:function(a){return/input|select|textarea|button/i.test(a.nodeName);},has:function(a,i,m){return jQuery.find(m[3],a).length;},header:function(a){return/h\d/i.test(a.nodeName);},animated:function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}}},parse:[/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,new RegExp("^([:.#]*)("+chars+"+)")],multiFilter:function(expr,elems,not){var old,cur=[];while(expr&&expr!=old){old=expr;var f=jQuery.filter(expr,elems,not);expr=f.t.replace(/^\s*,\s*/,"");cur=not?elems=f.r:jQuery.merge(cur,f.r);}return cur;},find:function(t,context){if(typeof t!="string")return[t];if(context&&context.nodeType!=1&&context.nodeType!=9)return[];context=context||document;var ret=[context],done=[],last,nodeName;while(t&&last!=t){var r=[];last=t;t=jQuery.trim(t);var foundToken=false,re=quickChild,m=re.exec(t);if(m){nodeName=m[1].toUpperCase();for(var i=0;ret[i];i++)for(var c=ret[i].firstChild;c;c=c.nextSibling)if(c.nodeType==1&&(nodeName=="*"||c.nodeName.toUpperCase()==nodeName))r.push(c);ret=r;t=t.replace(re,"");if(t.indexOf(" ")==0)continue;foundToken=true;}else{re=/^([>+~])\s*(\w*)/i;if((m=re.exec(t))!=null){r=[];var merge={};nodeName=m[2].toUpperCase();m=m[1];for(var j=0,rl=ret.length;j<rl;j++){var n=m=="~"||m=="+"?ret[j].nextSibling:ret[j].firstChild;for(;n;n=n.nextSibling)if(n.nodeType==1){var id=jQuery.data(n);if(m=="~"&&merge[id])break;if(!nodeName||n.nodeName.toUpperCase()==nodeName){if(m=="~")merge[id]=true;r.push(n);}if(m=="+")break;}}ret=r;t=jQuery.trim(t.replace(re,""));foundToken=true;}}if(t&&!foundToken){if(!t.indexOf(",")){if(context==ret[0])ret.shift();done=jQuery.merge(done,ret);r=ret=[context];t=" "+t.substr(1,t.length);}else{var re2=quickID;var m=re2.exec(t);if(m){m=[0,m[2],m[3],m[1]];}else{re2=quickClass;m=re2.exec(t);}m[2]=m[2].replace(/\\/g,"");var elem=ret[ret.length-1];if(m[1]=="#"&&elem&&elem.getElementById&&!jQuery.isXMLDoc(elem)){var oid=elem.getElementById(m[2]);if((jQuery.browser.msie||jQuery.browser.opera)&&oid&&typeof oid.id=="string"&&oid.id!=m[2])oid=jQuery('[@id="'+m[2]+'"]',elem)[0];ret=r=oid&&(!m[3]||jQuery.nodeName(oid,m[3]))?[oid]:[];}else{for(var i=0;ret[i];i++){var tag=m[1]=="#"&&m[3]?m[3]:m[1]!=""||m[0]==""?"*":m[2];if(tag=="*"&&ret[i].nodeName.toLowerCase()=="object")tag="param";r=jQuery.merge(r,ret[i].getElementsByTagName(tag));}if(m[1]==".")r=jQuery.classFilter(r,m[2]);if(m[1]=="#"){var tmp=[];for(var i=0;r[i];i++)if(r[i].getAttribute("id")==m[2]){tmp=[r[i]];break;}r=tmp;}ret=r;}t=t.replace(re2,"");}}if(t){var val=jQuery.filter(t,r);ret=r=val.r;t=jQuery.trim(val.t);}}if(t)ret=[];if(ret&&context==ret[0])ret.shift();done=jQuery.merge(done,ret);return done;},classFilter:function(r,m,not){m=" "+m+" ";var tmp=[];for(var i=0;r[i];i++){var pass=(" "+r[i].className+" ").indexOf(m)>=0;if(!not&&pass||not&&!pass)tmp.push(r[i]);}return tmp;},filter:function(t,r,not){var last;while(t&&t!=last){last=t;var p=jQuery.parse,m;for(var i=0;p[i];i++){m=p[i].exec(t);if(m){t=t.substring(m[0].length);m[2]=m[2].replace(/\\/g,"");break;}}if(!m)break;if(m[1]==":"&&m[2]=="not")r=isSimple.test(m[3])?jQuery.filter(m[3],r,true).r:jQuery(r).not(m[3]);else if(m[1]==".")r=jQuery.classFilter(r,m[2],not);else if(m[1]=="["){var tmp=[],type=m[3];for(var i=0,rl=r.length;i<rl;i++){var a=r[i],z=a[jQuery.props[m[2]]||m[2]];if(z==null||/href|src|selected/.test(m[2]))z=jQuery.attr(a,m[2])||'';if((type==""&&!!z||type=="="&&z==m[5]||type=="!="&&z!=m[5]||type=="^="&&z&&!z.indexOf(m[5])||type=="$="&&z.substr(z.length-m[5].length)==m[5]||(type=="*="||type=="~=")&&z.indexOf(m[5])>=0)^not)tmp.push(a);}r=tmp;}else if(m[1]==":"&&m[2]=="nth-child"){var merge={},tmp=[],test=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3]=="even"&&"2n"||m[3]=="odd"&&"2n+1"||!/\D/.test(m[3])&&"0n+"+m[3]||m[3]),first=(test[1]+(test[2]||1))-0,last=test[3]-0;for(var i=0,rl=r.length;i<rl;i++){var node=r[i],parentNode=node.parentNode,id=jQuery.data(parentNode);if(!merge[id]){var c=1;for(var n=parentNode.firstChild;n;n=n.nextSibling)if(n.nodeType==1)n.nodeIndex=c++;merge[id]=true;}var add=false;if(first==0){if(node.nodeIndex==last)add=true;}else if((node.nodeIndex-last)%first==0&&(node.nodeIndex-last)/first>=0)add=true;if(add^not)tmp.push(node);}r=tmp;}else{var fn=jQuery.expr[m[1]];if(typeof fn=="object")fn=fn[m[2]];if(typeof fn=="string")fn=eval("false||function(a,i){return "+fn+";}");r=jQuery.grep(r,function(elem,i){return fn(elem,i,m,r);},not);}}return{r:r,t:t};},dir:function(elem,dir){var matched=[],cur=elem[dir];while(cur&&cur!=document){if(cur.nodeType==1)matched.push(cur);cur=cur[dir];}return matched;},nth:function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir])if(cur.nodeType==1&&++num==result)break;return cur;},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType==1&&n!=elem)r.push(n);}return r;}});jQuery.event={add:function(elem,types,handler,data){if(elem.nodeType==3||elem.nodeType==8)return;if(jQuery.browser.msie&&elem.setInterval)elem=window;if(!handler.guid)handler.guid=this.guid++;if(data!=undefined){var fn=handler;handler=this.proxy(fn,function(){return fn.apply(this,arguments);});handler.data=data;}var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){if(typeof jQuery!="undefined"&&!jQuery.event.triggered)return jQuery.event.handle.apply(arguments.callee.elem,arguments);});handle.elem=elem;jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];handler.type=parts[1];var handlers=events[type];if(!handlers){handlers=events[type]={};if(!jQuery.event.special[type]||jQuery.event.special[type].setup.call(elem)===false){if(elem.addEventListener)elem.addEventListener(type,handle,false);else if(elem.attachEvent)elem.attachEvent("on"+type,handle);}}handlers[handler.guid]=handler;jQuery.event.global[type]=true;});elem=null;},guid:1,global:{},remove:function(elem,types,handler){if(elem.nodeType==3||elem.nodeType==8)return;var events=jQuery.data(elem,"events"),ret,index;if(events){if(types==undefined||(typeof types=="string"&&types.charAt(0)=="."))for(var type in events)this.remove(elem,type+(types||""));else{if(types.type){handler=types.handler;types=types.type;}jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];if(events[type]){if(handler)delete events[type][handler.guid];else
+for(handler in events[type])if(!parts[1]||events[type][handler].type==parts[1])delete events[type][handler];for(ret in events[type])break;if(!ret){if(!jQuery.event.special[type]||jQuery.event.special[type].teardown.call(elem)===false){if(elem.removeEventListener)elem.removeEventListener(type,jQuery.data(elem,"handle"),false);else if(elem.detachEvent)elem.detachEvent("on"+type,jQuery.data(elem,"handle"));}ret=null;delete events[type];}}});}for(ret in events)break;if(!ret){var handle=jQuery.data(elem,"handle");if(handle)handle.elem=null;jQuery.removeData(elem,"events");jQuery.removeData(elem,"handle");}}},trigger:function(type,data,elem,donative,extra){data=jQuery.makeArray(data);if(type.indexOf("!")>=0){type=type.slice(0,-1);var exclusive=true;}if(!elem){if(this.global[type])jQuery("*").add([window,document]).trigger(type,data);}else{if(elem.nodeType==3||elem.nodeType==8)return undefined;var val,ret,fn=jQuery.isFunction(elem[type]||null),event=!data[0]||!data[0].preventDefault;if(event){data.unshift({type:type,target:elem,preventDefault:function(){},stopPropagation:function(){},timeStamp:now()});data[0][expando]=true;}data[0].type=type;if(exclusive)data[0].exclusive=true;var handle=jQuery.data(elem,"handle");if(handle)val=handle.apply(elem,data);if((!fn||(jQuery.nodeName(elem,'a')&&type=="click"))&&elem["on"+type]&&elem["on"+type].apply(elem,data)===false)val=false;if(event)data.shift();if(extra&&jQuery.isFunction(extra)){ret=extra.apply(elem,val==null?data:data.concat(val));if(ret!==undefined)val=ret;}if(fn&&donative!==false&&val!==false&&!(jQuery.nodeName(elem,'a')&&type=="click")){this.triggered=true;try{elem[type]();}catch(e){}}this.triggered=false;}return val;},handle:function(event){var val,ret,namespace,all,handlers;event=arguments[0]=jQuery.event.fix(event||window.event);namespace=event.type.split(".");event.type=namespace[0];namespace=namespace[1];all=!namespace&&!event.exclusive;handlers=(jQuery.data(this,"events")||{})[event.type];for(var j in handlers){var handler=handlers[j];if(all||handler.type==namespace){event.handler=handler;event.data=handler.data;ret=handler.apply(this,arguments);if(val!==false)val=ret;if(ret===false){event.preventDefault();event.stopPropagation();}}}return val;},fix:function(event){if(event[expando]==true)return event;var originalEvent=event;event={originalEvent:originalEvent};var props="altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target timeStamp toElement type view wheelDelta which".split(" ");for(var i=props.length;i;i--)event[props[i]]=originalEvent[props[i]];event[expando]=true;event.preventDefault=function(){if(originalEvent.preventDefault)originalEvent.preventDefault();originalEvent.returnValue=false;};event.stopPropagation=function(){if(originalEvent.stopPropagation)originalEvent.stopPropagation();originalEvent.cancelBubble=true;};event.timeStamp=event.timeStamp||now();if(!event.target)event.target=event.srcElement||document;if(event.target.nodeType==3)event.target=event.target.parentNode;if(!event.relatedTarget&&event.fromElement)event.relatedTarget=event.fromElement==event.target?event.toElement:event.fromElement;if(event.pageX==null&&event.clientX!=null){var doc=document.documentElement,body=document.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc.clientTop||0);}if(!event.which&&((event.charCode||event.charCode===0)?event.charCode:event.keyCode))event.which=event.charCode||event.keyCode;if(!event.metaKey&&event.ctrlKey)event.metaKey=event.ctrlKey;if(!event.which&&event.button)event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)));return event;},proxy:function(fn,proxy){proxy.guid=fn.guid=fn.guid||proxy.guid||this.guid++;return proxy;},special:{ready:{setup:function(){bindReady();return;},teardown:function(){return;}},mouseenter:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseover",jQuery.event.special.mouseenter.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseover",jQuery.event.special.mouseenter.handler);return true;},handler:function(event){if(withinElement(event,this))return true;event.type="mouseenter";return jQuery.event.handle.apply(this,arguments);}},mouseleave:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseout",jQuery.event.special.mouseleave.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseout",jQuery.event.special.mouseleave.handler);return true;},handler:function(event){if(withinElement(event,this))return true;event.type="mouseleave";return jQuery.event.handle.apply(this,arguments);}}}};jQuery.fn.extend({bind:function(type,data,fn){return type=="unload"?this.one(type,data,fn):this.each(function(){jQuery.event.add(this,type,fn||data,fn&&data);});},one:function(type,data,fn){var one=jQuery.event.proxy(fn||data,function(event){jQuery(this).unbind(event,one);return(fn||data).apply(this,arguments);});return this.each(function(){jQuery.event.add(this,type,one,fn&&data);});},unbind:function(type,fn){return this.each(function(){jQuery.event.remove(this,type,fn);});},trigger:function(type,data,fn){return this.each(function(){jQuery.event.trigger(type,data,this,true,fn);});},triggerHandler:function(type,data,fn){return this[0]&&jQuery.event.trigger(type,data,this[0],false,fn);},toggle:function(fn){var args=arguments,i=1;while(i<args.length)jQuery.event.proxy(fn,args[i++]);return this.click(jQuery.event.proxy(fn,function(event){this.lastToggle=(this.lastToggle||0)%i;event.preventDefault();return args[this.lastToggle++].apply(this,arguments)||false;}));},hover:function(fnOver,fnOut){return this.bind('mouseenter',fnOver).bind('mouseleave',fnOut);},ready:function(fn){bindReady();if(jQuery.isReady)fn.call(document,jQuery);else
+jQuery.readyList.push(function(){return fn.call(this,jQuery);});return this;}});jQuery.extend({isReady:false,readyList:[],ready:function(){if(!jQuery.isReady){jQuery.isReady=true;if(jQuery.readyList){jQuery.each(jQuery.readyList,function(){this.call(document);});jQuery.readyList=null;}jQuery(document).triggerHandler("ready");}}});var readyBound=false;function bindReady(){if(readyBound)return;readyBound=true;if(document.addEventListener&&!jQuery.browser.opera)document.addEventListener("DOMContentLoaded",jQuery.ready,false);if(jQuery.browser.msie&&window==top)(function(){if(jQuery.isReady)return;try{document.documentElement.doScroll("left");}catch(error){setTimeout(arguments.callee,0);return;}jQuery.ready();})();if(jQuery.browser.opera)document.addEventListener("DOMContentLoaded",function(){if(jQuery.isReady)return;for(var i=0;i<document.styleSheets.length;i++)if(document.styleSheets[i].disabled){setTimeout(arguments.callee,0);return;}jQuery.ready();},false);if(jQuery.browser.safari){var numStyles;(function(){if(jQuery.isReady)return;if(document.readyState!="loaded"&&document.readyState!="complete"){setTimeout(arguments.callee,0);return;}if(numStyles===undefined)numStyles=jQuery("style, link[rel=stylesheet]").length;if(document.styleSheets.length!=numStyles){setTimeout(arguments.callee,0);return;}jQuery.ready();})();}jQuery.event.add(window,"load",jQuery.ready);}jQuery.each(("blur,focus,load,resize,scroll,unload,click,dblclick,"+"mousedown,mouseup,mousemove,mouseover,mouseout,change,select,"+"submit,keydown,keypress,keyup,error").split(","),function(i,name){jQuery.fn[name]=function(fn){return fn?this.bind(name,fn):this.trigger(name);};});var withinElement=function(event,elem){var parent=event.relatedTarget;while(parent&&parent!=elem)try{parent=parent.parentNode;}catch(error){parent=elem;}return parent==elem;};jQuery(window).bind("unload",function(){jQuery("*").add(document).unbind();});jQuery.fn.extend({_load:jQuery.fn.load,load:function(url,params,callback){if(typeof url!='string')return this._load(url);var off=url.indexOf(" ");if(off>=0){var selector=url.slice(off,url.length);url=url.slice(0,off);}callback=callback||function(){};var type="GET";if(params)if(jQuery.isFunction(params)){callback=params;params=null;}else{params=jQuery.param(params);type="POST";}var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(res,status){if(status=="success"||status=="notmodified")self.html(selector?jQuery("<div/>").append(res.responseText.replace(/<script(.|\s)*?\/script>/g,"")).find(selector):res.responseText);self.each(callback,[res.responseText,status,res]);}});return this;},serialize:function(){return jQuery.param(this.serializeArray());},serializeArray:function(){return this.map(function(){return jQuery.nodeName(this,"form")?jQuery.makeArray(this.elements):this;}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type));}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:val.constructor==Array?jQuery.map(val,function(val,i){return{name:elem.name,value:val};}):{name:elem.name,value:val};}).get();}});jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(i,o){jQuery.fn[o]=function(f){return this.bind(o,f);};});var jsc=now();jQuery.extend({get:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data=null;}return jQuery.ajax({type:"GET",url:url,data:data,success:callback,dataType:type});},getScript:function(url,callback){return jQuery.get(url,null,callback,"script");},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},post:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data={};}return jQuery.ajax({type:"POST",url:url,data:data,success:callback,dataType:type});},ajaxSetup:function(settings){jQuery.extend(jQuery.ajaxSettings,settings);},ajaxSettings:{url:location.href,global:true,type:"GET",timeout:0,contentType:"application/x-www-form-urlencoded",processData:true,async:true,data:null,username:null,password:null,accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(s){s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));var jsonp,jsre=/=\?(&|$)/g,status,data,type=s.type.toUpperCase();if(s.data&&s.processData&&typeof s.data!="string")s.data=jQuery.param(s.data);if(s.dataType=="jsonp"){if(type=="GET"){if(!s.url.match(jsre))s.url+=(s.url.match(/\?/)?"&":"?")+(s.jsonp||"callback")+"=?";}else if(!s.data||!s.data.match(jsre))s.data=(s.data?s.data+"&":"")+(s.jsonp||"callback")+"=?";s.dataType="json";}if(s.dataType=="json"&&(s.data&&s.data.match(jsre)||s.url.match(jsre))){jsonp="jsonp"+jsc++;if(s.data)s.data=(s.data+"").replace(jsre,"="+jsonp+"$1");s.url=s.url.replace(jsre,"="+jsonp+"$1");s.dataType="script";window[jsonp]=function(tmp){data=tmp;success();complete();window[jsonp]=undefined;try{delete window[jsonp];}catch(e){}if(head)head.removeChild(script);};}if(s.dataType=="script"&&s.cache==null)s.cache=false;if(s.cache===false&&type=="GET"){var ts=now();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"");}if(s.data&&type=="GET"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null;}if(s.global&&!jQuery.active++)jQuery.event.trigger("ajaxStart");var remote=/^(?:\w+:)?\/\/([^\/?#]+)/;if(s.dataType=="script"&&type=="GET"&&remote.test(s.url)&&remote.exec(s.url)[1]!=location.host){var head=document.getElementsByTagName("head")[0];var script=document.createElement("script");script.src=s.url;if(s.scriptCharset)script.charset=s.scriptCharset;if(!jsonp){var done=false;script.onload=script.onreadystatechange=function(){if(!done&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){done=true;success();complete();head.removeChild(script);}};}head.appendChild(script);return undefined;}var requestDone=false;var xhr=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();if(s.username)xhr.open(type,s.url,s.async,s.username,s.password);else
+xhr.open(type,s.url,s.async);try{if(s.data)xhr.setRequestHeader("Content-Type",s.contentType);if(s.ifModified)xhr.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT");xhr.setRequestHeader("X-Requested-With","XMLHttpRequest");xhr.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default);}catch(e){}if(s.beforeSend&&s.beforeSend(xhr,s)===false){s.global&&jQuery.active--;xhr.abort();return false;}if(s.global)jQuery.event.trigger("ajaxSend",[xhr,s]);var onreadystatechange=function(isTimeout){if(!requestDone&&xhr&&(xhr.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null;}status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xhr)&&"error"||s.ifModified&&jQuery.httpNotModified(xhr,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xhr,s.dataType,s.dataFilter);}catch(e){status="parsererror";}}if(status=="success"){var modRes;try{modRes=xhr.getResponseHeader("Last-Modified");}catch(e){}if(s.ifModified&&modRes)jQuery.lastModified[s.url]=modRes;if(!jsonp)success();}else
+jQuery.handleError(s,xhr,status);complete();if(s.async)xhr=null;}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0)setTimeout(function(){if(xhr){xhr.abort();if(!requestDone)onreadystatechange("timeout");}},s.timeout);}try{xhr.send(s.data);}catch(e){jQuery.handleError(s,xhr,null,e);}if(!s.async)onreadystatechange();function success(){if(s.success)s.success(data,status);if(s.global)jQuery.event.trigger("ajaxSuccess",[xhr,s]);}function complete(){if(s.complete)s.complete(xhr,status);if(s.global)jQuery.event.trigger("ajaxComplete",[xhr,s]);if(s.global&&!--jQuery.active)jQuery.event.trigger("ajaxStop");}return xhr;},handleError:function(s,xhr,status,e){if(s.error)s.error(xhr,status,e);if(s.global)jQuery.event.trigger("ajaxError",[xhr,s,e]);},active:0,httpSuccess:function(xhr){try{return!xhr.status&&location.protocol=="file:"||(xhr.status>=200&&xhr.status<300)||xhr.status==304||xhr.status==1223||jQuery.browser.safari&&xhr.status==undefined;}catch(e){}return false;},httpNotModified:function(xhr,url){try{var xhrRes=xhr.getResponseHeader("Last-Modified");return xhr.status==304||xhrRes==jQuery.lastModified[url]||jQuery.browser.safari&&xhr.status==undefined;}catch(e){}return false;},httpData:function(xhr,type,filter){var ct=xhr.getResponseHeader("content-type"),xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0,data=xml?xhr.responseXML:xhr.responseText;if(xml&&data.documentElement.tagName=="parsererror")throw"parsererror";if(filter)data=filter(data,type);if(type=="script")jQuery.globalEval(data);if(type=="json")data=eval("("+data+")");return data;},param:function(a){var s=[];if(a.constructor==Array||a.jquery)jQuery.each(a,function(){s.push(encodeURIComponent(this.name)+"="+encodeURIComponent(this.value));});else
+for(var j in a)if(a[j]&&a[j].constructor==Array)jQuery.each(a[j],function(){s.push(encodeURIComponent(j)+"="+encodeURIComponent(this));});else
+s.push(encodeURIComponent(j)+"="+encodeURIComponent(jQuery.isFunction(a[j])?a[j]():a[j]));return s.join("&").replace(/%20/g,"+");}});jQuery.fn.extend({show:function(speed,callback){return speed?this.animate({height:"show",width:"show",opacity:"show"},speed,callback):this.filter(":hidden").each(function(){this.style.display=this.oldblock||"";if(jQuery.css(this,"display")=="none"){var elem=jQuery("<"+this.tagName+" />").appendTo("body");this.style.display=elem.css("display");if(this.style.display=="none")this.style.display="block";elem.remove();}}).end();},hide:function(speed,callback){return speed?this.animate({height:"hide",width:"hide",opacity:"hide"},speed,callback):this.filter(":visible").each(function(){this.oldblock=this.oldblock||jQuery.css(this,"display");this.style.display="none";}).end();},_toggle:jQuery.fn.toggle,toggle:function(fn,fn2){return jQuery.isFunction(fn)&&jQuery.isFunction(fn2)?this._toggle.apply(this,arguments):fn?this.animate({height:"toggle",width:"toggle",opacity:"toggle"},fn,fn2):this.each(function(){jQuery(this)[jQuery(this).is(":hidden")?"show":"hide"]();});},slideDown:function(speed,callback){return this.animate({height:"show"},speed,callback);},slideUp:function(speed,callback){return this.animate({height:"hide"},speed,callback);},slideToggle:function(speed,callback){return this.animate({height:"toggle"},speed,callback);},fadeIn:function(speed,callback){return this.animate({opacity:"show"},speed,callback);},fadeOut:function(speed,callback){return this.animate({opacity:"hide"},speed,callback);},fadeTo:function(speed,to,callback){return this.animate({opacity:to},speed,callback);},animate:function(prop,speed,easing,callback){var optall=jQuery.speed(speed,easing,callback);return this[optall.queue===false?"each":"queue"](function(){if(this.nodeType!=1)return false;var opt=jQuery.extend({},optall),p,hidden=jQuery(this).is(":hidden"),self=this;for(p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden)return opt.complete.call(this);if(p=="height"||p=="width"){opt.display=jQuery.css(this,"display");opt.overflow=this.style.overflow;}}if(opt.overflow!=null)this.style.overflow="hidden";opt.curAnim=jQuery.extend({},prop);jQuery.each(prop,function(name,val){var e=new jQuery.fx(self,opt,name);if(/toggle|show|hide/.test(val))e[val=="toggle"?hidden?"show":"hide":val](prop);else{var parts=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),start=e.cur(true)||0;if(parts){var end=parseFloat(parts[2]),unit=parts[3]||"px";if(unit!="px"){self.style[name]=(end||1)+unit;start=((end||1)/e.cur(true))*start;self.style[name]=start+unit;}if(parts[1])end=((parts[1]=="-="?-1:1)*end)+start;e.custom(start,end,unit);}else
+e.custom(start,val,"");}});return true;});},queue:function(type,fn){if(jQuery.isFunction(type)||(type&&type.constructor==Array)){fn=type;type="fx";}if(!type||(typeof type=="string"&&!fn))return queue(this[0],type);return this.each(function(){if(fn.constructor==Array)queue(this,type,fn);else{queue(this,type).push(fn);if(queue(this,type).length==1)fn.call(this);}});},stop:function(clearQueue,gotoEnd){var timers=jQuery.timers;if(clearQueue)this.queue([]);this.each(function(){for(var i=timers.length-1;i>=0;i--)if(timers[i].elem==this){if(gotoEnd)timers[i](true);timers.splice(i,1);}});if(!gotoEnd)this.dequeue();return this;}});var queue=function(elem,type,array){if(elem){type=type||"fx";var q=jQuery.data(elem,type+"queue");if(!q||array)q=jQuery.data(elem,type+"queue",jQuery.makeArray(array));}return q;};jQuery.fn.dequeue=function(type){type=type||"fx";return this.each(function(){var q=queue(this,type);q.shift();if(q.length)q[0].call(this);});};jQuery.extend({speed:function(speed,easing,fn){var opt=speed&&speed.constructor==Object?speed:{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&easing.constructor!=Function&&easing};opt.duration=(opt.duration&&opt.duration.constructor==Number?opt.duration:jQuery.fx.speeds[opt.duration])||jQuery.fx.speeds.def;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false)jQuery(this).dequeue();if(jQuery.isFunction(opt.old))opt.old.call(this);};return opt;},easing:{linear:function(p,n,firstNum,diff){return firstNum+diff*p;},swing:function(p,n,firstNum,diff){return((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum;}},timers:[],timerId:null,fx:function(elem,options,prop){this.options=options;this.elem=elem;this.prop=prop;if(!options.orig)options.orig={};}});jQuery.fx.prototype={update:function(){if(this.options.step)this.options.step.call(this.elem,this.now,this);(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);if(this.prop=="height"||this.prop=="width")this.elem.style.display="block";},cur:function(force){if(this.elem[this.prop]!=null&&this.elem.style[this.prop]==null)return this.elem[this.prop];var r=parseFloat(jQuery.css(this.elem,this.prop,force));return r&&r>-10000?r:parseFloat(jQuery.curCSS(this.elem,this.prop))||0;},custom:function(from,to,unit){this.startTime=now();this.start=from;this.end=to;this.unit=unit||this.unit||"px";this.now=this.start;this.pos=this.state=0;this.update();var self=this;function t(gotoEnd){return self.step(gotoEnd);}t.elem=this.elem;jQuery.timers.push(t);if(jQuery.timerId==null){jQuery.timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;i<timers.length;i++)if(!timers[i]())timers.splice(i--,1);if(!timers.length){clearInterval(jQuery.timerId);jQuery.timerId=null;}},13);}},show:function(){this.options.orig[this.prop]=jQuery.attr(this.elem.style,this.prop);this.options.show=true;this.custom(0,this.cur());if(this.prop=="width"||this.prop=="height")this.elem.style[this.prop]="1px";jQuery(this.elem).show();},hide:function(){this.options.orig[this.prop]=jQuery.attr(this.elem.style,this.prop);this.options.hide=true;this.custom(this.cur(),0);},step:function(gotoEnd){var t=now();if(gotoEnd||t>this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var done=true;for(var i in this.options.curAnim)if(this.options.curAnim[i]!==true)done=false;if(done){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(jQuery.css(this.elem,"display")=="none")this.elem.style.display="block";}if(this.options.hide)this.elem.style.display="none";if(this.options.hide||this.options.show)for(var p in this.options.curAnim)jQuery.attr(this.elem.style,p,this.options.orig[p]);}if(done)this.options.complete.call(this.elem);return false;}else{var n=t-this.startTime;this.state=n/this.options.duration;this.pos=jQuery.easing[this.options.easing||(jQuery.easing.swing?"swing":"linear")](this.state,n,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update();}return true;}};jQuery.extend(jQuery.fx,{speeds:{slow:600,fast:200,def:400},step:{scrollLeft:function(fx){fx.elem.scrollLeft=fx.now;},scrollTop:function(fx){fx.elem.scrollTop=fx.now;},opacity:function(fx){jQuery.attr(fx.elem.style,"opacity",fx.now);},_default:function(fx){fx.elem.style[fx.prop]=fx.now+fx.unit;}}});jQuery.fn.offset=function(){var left=0,top=0,elem=this[0],results;if(elem)with(jQuery.browser){var parent=elem.parentNode,offsetChild=elem,offsetParent=elem.offsetParent,doc=elem.ownerDocument,safari2=safari&&parseInt(version)<522&&!/adobeair/i.test(userAgent),css=jQuery.curCSS,fixed=css(elem,"position")=="fixed";if(elem.getBoundingClientRect){var box=elem.getBoundingClientRect();add(box.left+Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),box.top+Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));add(-doc.documentElement.clientLeft,-doc.documentElement.clientTop);}else{add(elem.offsetLeft,elem.offsetTop);while(offsetParent){add(offsetParent.offsetLeft,offsetParent.offsetTop);if(mozilla&&!/^t(able|d|h)$/i.test(offsetParent.tagName)||safari&&!safari2)border(offsetParent);if(!fixed&&css(offsetParent,"position")=="fixed")fixed=true;offsetChild=/^body$/i.test(offsetParent.tagName)?offsetChild:offsetParent;offsetParent=offsetParent.offsetParent;}while(parent&&parent.tagName&&!/^body|html$/i.test(parent.tagName)){if(!/^inline|table.*$/i.test(css(parent,"display")))add(-parent.scrollLeft,-parent.scrollTop);if(mozilla&&css(parent,"overflow")!="visible")border(parent);parent=parent.parentNode;}if((safari2&&(fixed||css(offsetChild,"position")=="absolute"))||(mozilla&&css(offsetChild,"position")!="absolute"))add(-doc.body.offsetLeft,-doc.body.offsetTop);if(fixed)add(Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));}results={top:top,left:left};}function border(elem){add(jQuery.curCSS(elem,"borderLeftWidth",true),jQuery.curCSS(elem,"borderTopWidth",true));}function add(l,t){left+=parseInt(l,10)||0;top+=parseInt(t,10)||0;}return results;};jQuery.fn.extend({position:function(){var left=0,top=0,results;if(this[0]){var offsetParent=this.offsetParent(),offset=this.offset(),parentOffset=/^body|html$/i.test(offsetParent[0].tagName)?{top:0,left:0}:offsetParent.offset();offset.top-=num(this,'marginTop');offset.left-=num(this,'marginLeft');parentOffset.top+=num(offsetParent,'borderTopWidth');parentOffset.left+=num(offsetParent,'borderLeftWidth');results={top:offset.top-parentOffset.top,left:offset.left-parentOffset.left};}return results;},offsetParent:function(){var offsetParent=this[0].offsetParent;while(offsetParent&&(!/^body|html$/i.test(offsetParent.tagName)&&jQuery.css(offsetParent,'position')=='static'))offsetParent=offsetParent.offsetParent;return jQuery(offsetParent);}});jQuery.each(['Left','Top'],function(i,name){var method='scroll'+name;jQuery.fn[method]=function(val){if(!this[0])return;return val!=undefined?this.each(function(){this==window||this==document?window.scrollTo(!i?val:jQuery(window).scrollLeft(),i?val:jQuery(window).scrollTop()):this[method]=val;}):this[0]==window||this[0]==document?self[i?'pageYOffset':'pageXOffset']||jQuery.boxModel&&document.documentElement[method]||document.body[method]:this[0][method];};});jQuery.each(["Height","Width"],function(i,name){var tl=i?"Left":"Top",br=i?"Right":"Bottom";jQuery.fn["inner"+name]=function(){return this[name.toLowerCase()]()+num(this,"padding"+tl)+num(this,"padding"+br);};jQuery.fn["outer"+name]=function(margin){return this["inner"+name]()+num(this,"border"+tl+"Width")+num(this,"border"+br+"Width")+(margin?num(this,"margin"+tl)+num(this,"margin"+br):0);};});})();
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/jquery.ajaxfileupload.js b/forum/modules/template_loader.py/forum/skins/default/media/js/jquery.ajaxfileupload.js
new file mode 100644 (file)
index 0000000..7529277
--- /dev/null
@@ -0,0 +1,195 @@
+jQuery.extend({
+    createUploadIframe: function(id, uri){
+        //create frame
+        var frameId = 'jUploadFrame' + id;           
+        if(window.ActiveXObject) {
+            var io = document.createElement('<iframe id="' + frameId + '" name="' + frameId + '" />');
+            if(typeof uri== 'boolean'){
+                io.src = 'javascript:false';
+            }
+            else if(typeof uri== 'string'){
+                io.src = uri;
+            }
+        }
+        else {
+            var io = document.createElement('iframe');
+            io.id = frameId;
+            io.name = frameId;
+        }
+        io.style.position = 'absolute';
+        io.style.top = '-1000px';
+        io.style.left = '-1000px';
+
+        document.body.appendChild(io);
+        return io;
+    },
+    createUploadForm: function(id, fileElementId)
+       {
+               //create form   
+               var formId = 'jUploadForm' + id;
+               var fileId = 'jUploadFile' + id;
+               var form = $('<form  action="" method="POST" name="' + formId + '" id="' + formId 
+            + '" enctype="multipart/form-data"></form>');      
+               var oldElement = $('#' + fileElementId);
+               var newElement = $(oldElement).clone();
+               $(oldElement).attr('id', fileId);
+               $(oldElement).before(newElement);
+               $(oldElement).appendTo(form);
+               //set attributes
+               $(form).css('position', 'absolute');
+               $(form).css('top', '-1200px');
+               $(form).css('left', '-1200px');
+               $(form).appendTo('body');               
+               return form;
+    },
+
+    ajaxFileUpload: function(s) {
+        // TODO introduce global settings, allowing the client to modify them for all requests, not only timeout               
+        s = jQuery.extend({}, jQuery.ajaxSettings, s);
+        var id = new Date().getTime()        
+               var form = jQuery.createUploadForm(id, s.fileElementId);
+               var io = jQuery.createUploadIframe(id, s.secureuri);
+               var frameId = 'jUploadFrame' + id;
+               var formId = 'jUploadForm' + id;                
+        // Watch for a new set of requests
+        if ( s.global && ! jQuery.active++ )
+               {
+                       jQuery.event.trigger( "ajaxStart" );
+               }            
+        var requestDone = false;
+        // Create the request object
+        var xml = {}   
+        if ( s.global )
+            jQuery.event.trigger("ajaxSend", [xml, s]);
+        // Wait for a response to come back
+        var uploadCallback = function(isTimeout)
+               {                       
+                       var io = document.getElementById(frameId);
+            try {                              
+                               if(io.contentWindow){
+                                        xml.responseText = io.contentWindow.document.body ? 
+                        io.contentWindow.document.body.innerText : null;
+                        xml.responseXML = io.contentWindow.document.XMLDocument ? 
+                        io.contentWindow.document.XMLDocument : io.contentWindow.document;
+                                        
+                               }
+                else if(io.contentDocument)
+                               {
+                                       xml.responseText = io.contentDocument.document.body ? 
+                        io.contentDocument.document.body.textContent || document.body.innerText : null;
+                       xml.responseXML = io.contentDocument.document.XMLDocument ? 
+                        io.contentDocument.document.XMLDocument : io.contentDocument.document;
+                               }                                               
+            }
+            catch(e)
+                       {
+                               jQuery.handleError(s, xml, null, e);
+                       }
+            if ( xml || isTimeout == "timeout") 
+                       {                               
+                requestDone = true;
+                var status;
+                try {
+                    status = isTimeout != "timeout" ? "success" : "error";
+                    // Make sure that the request was successful or notmodified
+                    if ( status != "error" )
+                                       {
+                        // process the data (runs the xml through httpData regardless of callback)
+                        var data = jQuery.uploadHttpData( xml, s.dataType );    
+                        // If a local callback was specified, fire it and pass it the data
+                        if ( s.success )
+                            s.success( data, status );
+    
+                        // Fire the global callback
+                        if( s.global )
+                            jQuery.event.trigger( "ajaxSuccess", [xml, s] );
+                    } else
+                        jQuery.handleError(s, xml, status);
+                } catch(e) 
+                               {
+                    status = "error";
+                    jQuery.handleError(s, xml, status, e);
+                }
+
+                // The request was completed
+                if( s.global )
+                    jQuery.event.trigger( "ajaxComplete", [xml, s] );
+
+                // Handle the global AJAX counter
+                if ( s.global && ! --jQuery.active )
+                    jQuery.event.trigger( "ajaxStop" );
+
+                // Process result
+                if ( s.complete )
+                    s.complete(xml, status);
+
+                jQuery(io).unbind();
+
+                setTimeout(function()
+                    {  try 
+                        {
+                            $(io).remove();
+                            $(form).remove();  
+                            
+                        } catch(e) {
+                            jQuery.handleError(s, xml, null, e);
+                        }                                                                      
+                    }, 100)
+                xml = null;
+            }
+        }
+        // Timeout checker
+        if ( s.timeout > 0 ) {
+            setTimeout(function(){
+                // Check to see if the request is still happening
+                if( !requestDone ) uploadCallback( "timeout" );
+            }, s.timeout);
+        }
+        try 
+               {
+           // var io = $('#' + frameId);
+                       var form = $('#' + formId);
+                       $(form).attr('action', s.url);
+                       $(form).attr('method', 'POST');
+                       $(form).attr('target', frameId);
+            if(form.encoding)
+                       {
+                form.encoding = 'multipart/form-data';                         
+            }
+            else
+                       {                               
+                form.enctype = 'multipart/form-data';
+            }                  
+            $(form).submit();
+
+        } catch(e) 
+               {                       
+            jQuery.handleError(s, xml, null, e);
+        }
+        if(window.attachEvent){
+            document.getElementById(frameId).attachEvent('onload', uploadCallback);
+        }
+        else{
+            document.getElementById(frameId).addEventListener('load', uploadCallback, false);
+        }              
+        return {abort: function () {}};        
+
+    },
+
+    uploadHttpData: function( r, type ) {
+        var data = !type;
+        data = type == "xml" || data ? r.responseXML : r.responseText;
+        // If the type is "script", eval it in global context
+        if ( type == "script" )
+            jQuery.globalEval( data );
+        // Get the JavaScript object, if JSON is used.
+        if ( type == "json" )
+            eval( "data = " + data );
+        // evaluate scripts within html
+        if ( type == "html" )
+            jQuery("<div>").html(data).evalScripts();
+                       //alert($('param', data).each(function(){alert($(this).attr('value'));}));
+        return data;
+    }
+})
+
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/jquery.flot.js b/forum/modules/template_loader.py/forum/skins/default/media/js/jquery.flot.js
new file mode 100644 (file)
index 0000000..83b6192
--- /dev/null
@@ -0,0 +1,2421 @@
+/* Javascript plotting library for jQuery, v. 0.5.
+ *
+ * Released under the MIT license by IOLA, December 2007.
+ *
+ */
+
+(function($) {
+    function Plot(target_, data_, options_) {
+        // data is on the form:
+        //   [ series1, series2 ... ]
+        // where series is either just the data as [ [x1, y1], [x2, y2], ... ]
+        // or { data: [ [x1, y1], [x2, y2], ... ], label: "some label" }
+        
+        var series = [],
+            options = {
+                // the color theme used for graphs
+                colors: ["#edc240", "#afd8f8", "#cb4b4b", "#4da74d", "#9440ed"],
+                legend: {
+                    show: true,
+                    noColumns: 1, // number of colums in legend table
+                    labelFormatter: null, // fn: string -> string
+                    labelBoxBorderColor: "#ccc", // border color for the little label boxes
+                    container: null, // container (as jQuery object) to put legend in, null means default on top of graph
+                    position: "ne", // position of default legend container within plot
+                    margin: 5, // distance from grid edge to default legend container within plot
+                    backgroundColor: null, // null means auto-detect
+                    backgroundOpacity: 0.85 // set to 0 to avoid background
+                },
+                xaxis: {
+                    mode: null, // null or "time"
+                    min: null, // min. value to show, null means set automatically
+                    max: null, // max. value to show, null means set automatically
+                    autoscaleMargin: null, // margin in % to add if auto-setting min/max
+                    ticks: null, // either [1, 3] or [[1, "a"], 3] or (fn: axis info -> ticks) or app. number of ticks for auto-ticks
+                    tickFormatter: null, // fn: number -> string
+                    labelWidth: null, // size of tick labels in pixels
+                    labelHeight: null,
+                    
+                    // mode specific options
+                    tickDecimals: null, // no. of decimals, null means auto
+                    tickSize: null, // number or [number, "unit"]
+                    minTickSize: null, // number or [number, "unit"]
+                    monthNames: null, // list of names of months
+                    timeformat: null // format string to use
+                },
+                yaxis: {
+                    autoscaleMargin: 0.02
+                },
+                x2axis: {
+                    autoscaleMargin: null
+                },
+                y2axis: {
+                    autoscaleMargin: 0.02
+                },              
+                points: {
+                    show: false,
+                    radius: 3,
+                    lineWidth: 2, // in pixels
+                    fill: true,
+                    fillColor: "#ffffff"
+                },
+                lines: {
+                    // we don't put in show: false so we can see
+                    // whether lines were actively disabled 
+                    lineWidth: 2, // in pixels
+                    fill: false,
+                    fillColor: null,
+                    steps: false
+                },
+                bars: {
+                    show: false,
+                    lineWidth: 2, // in pixels
+                    barWidth: 1, // in units of the x axis
+                    fill: true,
+                    fillColor: null,
+                    align: "left", // or "center" 
+                    horizontal: false // when horizontal, left is now top
+                },
+                threshold: null, // or { below: number, color: color spec}
+                grid: {
+                    color: "#545454", // primary color used for outline and labels
+                    backgroundColor: null, // null for transparent, else color
+                    tickColor: "#dddddd", // color used for the ticks
+                    labelMargin: 5, // in pixels
+                    borderWidth: 2, // in pixels
+                    borderColor: null, // set if different from the grid color
+                    markings: null, // array of ranges or fn: axes -> array of ranges
+                    markingsColor: "#f4f4f4",
+                    markingsLineWidth: 2,
+                    // interactive stuff
+                    clickable: false,
+                    hoverable: false,
+                    autoHighlight: true, // highlight in case mouse is near
+                    mouseActiveRadius: 10 // how far the mouse can be away to activate an item
+                },
+                selection: {
+                    mode: null, // one of null, "x", "y" or "xy"
+                    color: "#e8cfac"
+                },
+                crosshair: {
+                    mode: null, // one of null, "x", "y" or "xy",
+                    color: "#aa0000"
+                },
+                shadowSize: 3
+            },
+        canvas = null,      // the canvas for the plot itself
+        overlay = null,     // canvas for interactive stuff on top of plot
+        eventHolder = null, // jQuery object that events should be bound to
+        ctx = null, octx = null,
+        target = $(target_),
+        axes = { xaxis: {}, yaxis: {}, x2axis: {}, y2axis: {} },
+        plotOffset = { left: 0, right: 0, top: 0, bottom: 0},
+        canvasWidth = 0, canvasHeight = 0,
+        plotWidth = 0, plotHeight = 0,
+        // dedicated to storing data for buggy standard compliance cases
+        workarounds = {};
+        
+        this.setData = setData;
+        this.setupGrid = setupGrid;
+        this.draw = draw;
+        this.clearSelection = clearSelection;
+        this.setSelection = setSelection;
+        this.getCanvas = function() { return canvas; };
+        this.getPlotOffset = function() { return plotOffset; };
+        this.getData = function() { return series; };
+        this.getAxes = function() { return axes; };
+        this.setCrosshair = setCrosshair;
+        this.clearCrosshair = function () { setCrosshair(null); };
+        this.highlight = highlight;
+        this.unhighlight = unhighlight;
+        
+        // initialize
+        parseOptions(options_);
+        setData(data_);
+        constructCanvas();
+        setupGrid();
+        draw();
+
+
+        function setData(d) {
+            series = parseData(d);
+
+            fillInSeriesOptions();
+            processData();
+        }
+        
+        function parseData(d) {
+            var res = [];
+            for (var i = 0; i < d.length; ++i) {
+                var s;
+                if (d[i].data) {
+                    s = {};
+                    for (var v in d[i])
+                        s[v] = d[i][v];
+                }
+                else {
+                    s = { data: d[i] };
+                }
+                res.push(s);
+            }
+
+            return res;
+        }
+        
+        function parseOptions(o) {
+            $.extend(true, options, o);
+            if (options.grid.borderColor == null)
+                options.grid.borderColor = options.grid.color
+            // backwards compatibility, to be removed in future
+            if (options.xaxis.noTicks && options.xaxis.ticks == null)
+                options.xaxis.ticks = options.xaxis.noTicks;
+            if (options.yaxis.noTicks && options.yaxis.ticks == null)
+                options.yaxis.ticks = options.yaxis.noTicks;
+            if (options.grid.coloredAreas)
+                options.grid.markings = options.grid.coloredAreas;
+            if (options.grid.coloredAreasColor)
+                options.grid.markingsColor = options.grid.coloredAreasColor;
+        }
+
+        function fillInSeriesOptions() {
+            var i;
+            
+            // collect what we already got of colors
+            var neededColors = series.length,
+                usedColors = [],
+                assignedColors = [];
+            for (i = 0; i < series.length; ++i) {
+                var sc = series[i].color;
+                if (sc != null) {
+                    --neededColors;
+                    if (typeof sc == "number")
+                        assignedColors.push(sc);
+                    else
+                        usedColors.push(parseColor(series[i].color));
+                }
+            }
+            
+            // we might need to generate more colors if higher indices
+            // are assigned
+            for (i = 0; i < assignedColors.length; ++i) {
+                neededColors = Math.max(neededColors, assignedColors[i] + 1);
+            }
+
+            // produce colors as needed
+            var colors = [], variation = 0;
+            i = 0;
+            while (colors.length < neededColors) {
+                var c;
+                if (options.colors.length == i) // check degenerate case
+                    c = new Color(100, 100, 100);
+                else
+                    c = parseColor(options.colors[i]);
+
+                // vary color if needed
+                var sign = variation % 2 == 1 ? -1 : 1;
+                var factor = 1 + sign * Math.ceil(variation / 2) * 0.2;
+                c.scale(factor, factor, factor);
+
+                // FIXME: if we're getting to close to something else,
+                // we should probably skip this one
+                colors.push(c);
+                
+                ++i;
+                if (i >= options.colors.length) {
+                    i = 0;
+                    ++variation;
+                }
+            }
+
+            // fill in the options
+            var colori = 0, s;
+            for (i = 0; i < series.length; ++i) {
+                s = series[i];
+
+                // assign colors
+                if (s.color == null) {
+                    s.color = colors[colori].toString();
+                    ++colori;
+                }
+                else if (typeof s.color == "number")
+                    s.color = colors[s.color].toString();
+
+                // copy the rest
+                s.lines = $.extend(true, {}, options.lines, s.lines);
+                s.points = $.extend(true, {}, options.points, s.points);
+                s.bars = $.extend(true, {}, options.bars, s.bars);
+
+                // turn on lines automatically in case nothing is set
+                if (s.lines.show == null && !s.bars.show && !s.points.show)
+                    s.lines.show = true;
+                if (s.shadowSize == null)
+                    s.shadowSize = options.shadowSize;
+
+                if (!s.xaxis)
+                    s.xaxis = axes.xaxis;
+
+                if (s.xaxis == 1)
+                    s.xaxis = axes.xaxis;
+                else if (s.xaxis == 2)
+                    s.xaxis = axes.x2axis;
+
+                if (!s.yaxis)
+                    s.yaxis = axes.yaxis;
+
+                if (s.yaxis == 1)
+                    s.yaxis = axes.yaxis;
+                else if (s.yaxis == 2)
+                    s.yaxis = axes.y2axis;
+
+                if (!s.threshold)
+                    s.threshold = options.threshold;
+                s.subseries = null;
+            }
+        }
+        
+        function processData() {
+            var topSentry = Number.POSITIVE_INFINITY,
+                bottomSentry = Number.NEGATIVE_INFINITY,
+                axis, i, j, k, m, s;
+
+            for (axis in axes) {
+                axes[axis].datamin = topSentry;
+                axes[axis].datamax = bottomSentry;
+                axes[axis].min = options[axis].min;
+                axes[axis].max = options[axis].max;
+                axes[axis].used = false;
+            }
+            
+            for (i = 0; i < series.length; ++i) {
+                s = series[i];
+                s.datapoints = { points: [], incr: 2 };
+                
+                var data = s.data,
+                    points = s.datapoints.points,
+                    axisx = s.xaxis, axisy = s.yaxis,
+                    xmin = topSentry, xmax = bottomSentry,
+                    ymin = topSentry, ymax = bottomSentry,
+                    x, y, p, incr, format = [];
+
+                // determine the increment
+                if (s.bars.show) {
+                    s.datapoints.incr = 3;
+                    format.push({ d: 0 });
+                }
+
+                /*
+                // examine data to find out how to copy
+                for (j = 0; j < data.length; ++j) {
+                }*/
+                
+                
+                axisx.used = axisy.used = true;
+                incr = s.datapoints.incr;
+                
+                for (j = k = 0; j < data.length; ++j, k += incr) {
+                    p = data[j];
+                    x = null;
+                    y = null;
+
+                    if (data[j] != null) {
+                        x = p[0];
+                        y = p[1];
+                    }
+                    
+                    // convert to number
+                    if (x != null && !isNaN(x = +x)) {
+                        if (x < xmin)
+                            xmin = x;
+                        if (x > xmax)
+                            xmax = x
+                    }
+                    else
+                        x = null;
+                    
+                    if (y != null && !isNaN(y = +y)) {
+                        if (y < ymin)
+                            ymin = y;
+                        if (y > ymax)
+                            ymax = y;
+                    }
+                    else
+                        y = null;
+
+                    if (x == null || y == null)
+                        x = y = null; // make sure everything is cleared
+
+                    for (m = 2; m < incr; ++m)
+                        points[k + m] = p[m] == null ? format[m-2].d : p[m];
+
+                    points[k + 1] = y;
+                    points[k] = x;
+                }
+
+                if (s.bars.show) {
+                    // make sure we got room for the bar on the dancing floor
+                    var delta = s.bars.align == "left" ? 0 : -s.bars.barWidth/2;
+                    if(s.bars.horizontal) {
+                        ymin += delta;
+                        ymax += delta + s.bars.barWidth;
+                    }
+                    else {
+                        xmin += delta;
+                        xmax += delta + s.bars.barWidth;
+                    }
+                }
+                
+                axisx.datamin = Math.min(axisx.datamin, xmin);
+                axisx.datamax = Math.max(axisx.datamax, xmax);
+                axisy.datamin = Math.min(axisy.datamin, ymin);
+                axisy.datamax = Math.max(axisy.datamax, ymax);
+
+                
+                // step charts
+                if (s.lines.show && s.lines.steps) {
+                    p = [];
+                    // copy, inserting extra points to make steps
+                    for (j = k = 0; j < points.length; j += incr, k += incr) {
+                        x = points[j];
+                        y = points[j + 1];
+                        if (j > 0
+                            && points[j - incr] != null
+                            && x != null
+                            && points[j - incr + 1] != y) {
+                            p[k] = x;
+                            p[k + 1] = points[j - incr + 1];
+                            k += incr;
+                        }
+                        
+                        p[k] = x;
+                        p[k + 1] = y;
+                    }
+                    s.datapoints.linespoints = p;
+                }
+
+                // possibly split data points because of threshold
+                if (s.threshold) {
+                    var orig = $.extend({}, s), thresholded = $.extend({}, s);
+                    orig.datapoints = { points: [], incr: incr };
+                    thresholded.datapoints = { points: [], incr: incr };
+                    
+                    thresholded.color = s.threshold.color;
+
+                    var below = s.threshold.below,
+                        origpoints = orig.datapoints.points,
+                        threspoints = thresholded.datapoints.points;
+
+                    // ordinary points
+                    for (j = 0; j < points.length; j += incr) {
+                        x = points[j];
+                        y = points[j + 1];
+
+                        if (y < below)
+                            p = threspoints;
+                        else
+                            p = origpoints;
+
+                        p.push(x);
+                        p.push(y);
+                    }
+
+                    // possibly split lines
+                    if (s.lines.show) {
+                        var lp = s.datapoints.linespoints || points;
+                        
+                        origpoints = [];
+                        threspoints = [];
+                        p = origpoints;
+                        
+                        for (j = 0; j < lp.length; j += incr) {
+                            x = lp[j];
+                            y = lp[j + 1];
+
+                            var prevp = p;
+                            if (y != null) {
+                                if (y < below)
+                                    p = threspoints;
+                                else
+                                    p = origpoints;
+                            }
+
+                            if (p != prevp && x != null && j > 0 && lp[j - incr] != null) {
+                                // find intersection and add it to both
+                                k = (x - lp[j - incr]) / (y - lp[j - incr + 1]) * (below - y) + x;
+                                prevp.push(k);
+                                prevp.push(below);
+                                p.push(null); // start new segment
+                                p.push(null);
+                                p.push(k);
+                                p.push(below);
+                            }
+                            
+                            p.push(x);
+                            p.push(y);
+                        }
+
+                        orig.datapoints.linespoints = origpoints
+                        thresholded.datapoints.linespoints = threspoints;
+                    }
+
+                    s.subseries = [orig, thresholded];
+                }
+            }
+        }
+
+        function constructCanvas() {
+            function makeCanvas(width, height) {
+                var c = document.createElement('canvas');
+                c.width = width;
+                c.height = height;
+                if ($.browser.msie) // excanvas hack
+                    c = window.G_vmlCanvasManager.initElement(c);
+                return c;
+            }
+            
+            canvasWidth = target.width();
+            canvasHeight = target.height();
+            target.html(""); // clear target
+            if (target.css("position") == 'static')
+                target.css("position", "relative"); // for positioning labels and overlay
+
+            if (canvasWidth <= 0 || canvasHeight <= 0)
+                throw "Invalid dimensions for plot, width = " + canvasWidth + ", height = " + canvasHeight;
+
+            // the canvas
+            canvas = $(makeCanvas(canvasWidth, canvasHeight)).appendTo(target).get(0);
+            ctx = canvas.getContext("2d");
+
+            // overlay canvas for interactive features
+            overlay = $(makeCanvas(canvasWidth, canvasHeight)).css({ position: 'absolute', left: 0, top: 0 }).appendTo(target).get(0);
+            octx = overlay.getContext("2d");
+
+            // we include the canvas in the event holder too, because IE 7
+            // sometimes has trouble with the stacking order
+            eventHolder = $([overlay, canvas]);
+
+            // bind events
+            if (options.selection.mode != null || options.crosshair.mode != null
+                || options.grid.hoverable) {
+                // FIXME: temp. work-around until jQuery bug 4398 is fixed
+                eventHolder.each(function () {
+                    this.onmousemove = onMouseMove;
+                });
+
+                if (options.selection.mode != null)
+                    eventHolder.mousedown(onMouseDown);
+            }
+
+            if (options.crosshair.mode != null)
+                eventHolder.mouseout(onMouseOut);
+            
+            if (options.grid.clickable)
+                eventHolder.click(onClick);
+        }
+
+        function setupGrid() {
+            function setupAxis(axis, options) {
+                setRange(axis, options);
+                prepareTickGeneration(axis, options);
+                setTicks(axis, options);
+                // add transformation helpers
+                if (axis == axes.xaxis || axis == axes.x2axis) {
+                    // data point to canvas coordinate
+                    axis.p2c = function (p) { return (p - axis.min) * axis.scale; };
+                    // canvas coordinate to data point 
+                    axis.c2p = function (c) { return axis.min + c / axis.scale; };
+                }
+                else {
+                    axis.p2c = function (p) { return (axis.max - p) * axis.scale; };
+                    axis.c2p = function (p) { return axis.max - p / axis.scale; };
+                }
+            }
+
+            for (var axis in axes)
+                setupAxis(axes[axis], options[axis]);
+
+            setSpacing();
+            insertLabels();
+            insertLegend();
+        }
+        
+        function setRange(axis, axisOptions) {
+            var min = axisOptions.min != null ? +axisOptions.min : axis.datamin,
+                max = axisOptions.max != null ? +axisOptions.max : axis.datamax;
+
+            // degenerate case
+            if (min == Number.POSITIVE_INFINITY)
+                min = 0;
+            if (max == Number.NEGATIVE_INFINITY)
+                max = 1;
+            
+            if (max - min == 0.0) {
+                // degenerate case
+                var widen = max == 0 ? 1 : 0.01;
+
+                if (axisOptions.min == null)
+                    min -= widen;
+                // alway widen max if we couldn't widen min to ensure we
+                // don't fall into min == max which doesn't work
+                if (axisOptions.max == null || axisOptions.min != null)
+                    max += widen;
+            }
+            else {
+                // consider autoscaling
+                var margin = axisOptions.autoscaleMargin;
+                if (margin != null) {
+                    if (axisOptions.min == null) {
+                        min -= (max - min) * margin;
+                        // make sure we don't go below zero if all values
+                        // are positive
+                        if (min < 0 && axis.datamin >= 0)
+                            min = 0;
+                    }
+                    if (axisOptions.max == null) {
+                        max += (max - min) * margin;
+                        if (max > 0 && axis.datamax <= 0)
+                            max = 0;
+                    }
+                }
+            }
+            axis.min = min;
+            axis.max = max;
+        }
+
+        function prepareTickGeneration(axis, axisOptions) {
+            // estimate number of ticks
+            var noTicks;
+            if (typeof axisOptions.ticks == "number" && axisOptions.ticks > 0)
+                noTicks = axisOptions.ticks;
+            else if (axis == axes.xaxis || axis == axes.x2axis)
+                noTicks = canvasWidth / 100;
+            else
+                noTicks = canvasHeight / 60;
+            
+            var delta = (axis.max - axis.min) / noTicks;
+            var size, generator, unit, formatter, i, magn, norm;
+
+            if (axisOptions.mode == "time") {
+                // pretty handling of time
+                
+                // map of app. size of time units in milliseconds
+                var timeUnitSize = {
+                    "second": 1000,
+                    "minute": 60 * 1000,
+                    "hour": 60 * 60 * 1000,
+                    "day": 24 * 60 * 60 * 1000,
+                    "month": 30 * 24 * 60 * 60 * 1000,
+                    "year": 365.2425 * 24 * 60 * 60 * 1000
+                };
+
+
+                // the allowed tick sizes, after 1 year we use
+                // an integer algorithm
+                var spec = [
+                    [1, "second"], [2, "second"], [5, "second"], [10, "second"],
+                    [30, "second"], 
+                    [1, "minute"], [2, "minute"], [5, "minute"], [10, "minute"],
+                    [30, "minute"], 
+                    [1, "hour"], [2, "hour"], [4, "hour"],
+                    [8, "hour"], [12, "hour"],
+                    [1, "day"], [2, "day"], [3, "day"],
+                    [0.25, "month"], [0.5, "month"], [1, "month"],
+                    [2, "month"], [3, "month"], [6, "month"],
+                    [1, "year"]
+                ];
+
+                var minSize = 0;
+                if (axisOptions.minTickSize != null) {
+                    if (typeof axisOptions.tickSize == "number")
+                        minSize = axisOptions.tickSize;
+                    else
+                        minSize = axisOptions.minTickSize[0] * timeUnitSize[axisOptions.minTickSize[1]];
+                }
+
+                for (i = 0; i < spec.length - 1; ++i)
+                    if (delta < (spec[i][0] * timeUnitSize[spec[i][1]]
+                                 + spec[i + 1][0] * timeUnitSize[spec[i + 1][1]]) / 2
+                       && spec[i][0] * timeUnitSize[spec[i][1]] >= minSize)
+                        break;
+                size = spec[i][0];
+                unit = spec[i][1];
+                
+                // special-case the possibility of several years
+                if (unit == "year") {
+                    magn = Math.pow(10, Math.floor(Math.log(delta / timeUnitSize.year) / Math.LN10));
+                    norm = (delta / timeUnitSize.year) / magn;
+                    if (norm < 1.5)
+                        size = 1;
+                    else if (norm < 3)
+                        size = 2;
+                    else if (norm < 7.5)
+                        size = 5;
+                    else
+                        size = 10;
+
+                    size *= magn;
+                }
+
+                if (axisOptions.tickSize) {
+                    size = axisOptions.tickSize[0];
+                    unit = axisOptions.tickSize[1];
+                }
+                
+                generator = function(axis) {
+                    var ticks = [],
+                        tickSize = axis.tickSize[0], unit = axis.tickSize[1],
+                        d = new Date(axis.min);
+                    
+                    var step = tickSize * timeUnitSize[unit];
+
+                    if (unit == "second")
+                        d.setUTCSeconds(floorInBase(d.getUTCSeconds(), tickSize));
+                    if (unit == "minute")
+                        d.setUTCMinutes(floorInBase(d.getUTCMinutes(), tickSize));
+                    if (unit == "hour")
+                        d.setUTCHours(floorInBase(d.getUTCHours(), tickSize));
+                    if (unit == "month")
+                        d.setUTCMonth(floorInBase(d.getUTCMonth(), tickSize));
+                    if (unit == "year")
+                        d.setUTCFullYear(floorInBase(d.getUTCFullYear(), tickSize));
+                    
+                    // reset smaller components
+                    d.setUTCMilliseconds(0);
+                    if (step >= timeUnitSize.minute)
+                        d.setUTCSeconds(0);
+                    if (step >= timeUnitSize.hour)
+                        d.setUTCMinutes(0);
+                    if (step >= timeUnitSize.day)
+                        d.setUTCHours(0);
+                    if (step >= timeUnitSize.day * 4)
+                        d.setUTCDate(1);
+                    if (step >= timeUnitSize.year)
+                        d.setUTCMonth(0);
+
+
+                    var carry = 0, v = Number.NaN, prev;
+                    do {
+                        prev = v;
+                        v = d.getTime();
+                        ticks.push({ v: v, label: axis.tickFormatter(v, axis) });
+                        if (unit == "month") {
+                            if (tickSize < 1) {
+                                // a bit complicated - we'll divide the month
+                                // up but we need to take care of fractions
+                                // so we don't end up in the middle of a day
+                                d.setUTCDate(1);
+                                var start = d.getTime();
+                                d.setUTCMonth(d.getUTCMonth() + 1);
+                                var end = d.getTime();
+                                d.setTime(v + carry * timeUnitSize.hour + (end - start) * tickSize);
+                                carry = d.getUTCHours();
+                                d.setUTCHours(0);
+                            }
+                            else
+                                d.setUTCMonth(d.getUTCMonth() + tickSize);
+                        }
+                        else if (unit == "year") {
+                            d.setUTCFullYear(d.getUTCFullYear() + tickSize);
+                        }
+                        else
+                            d.setTime(v + step);
+                    } while (v < axis.max && v != prev);
+
+                    return ticks;
+                };
+
+                formatter = function (v, axis) {
+                    var d = new Date(v);
+
+                    // first check global format
+                    if (axisOptions.timeformat != null)
+                        return $.plot.formatDate(d, axisOptions.timeformat, axisOptions.monthNames);
+                    
+                    var t = axis.tickSize[0] * timeUnitSize[axis.tickSize[1]];
+                    var span = axis.max - axis.min;
+                    
+                    if (t < timeUnitSize.minute)
+                        fmt = "%h:%M:%S";
+                    else if (t < timeUnitSize.day) {
+                        if (span < 2 * timeUnitSize.day)
+                            fmt = "%h:%M";
+                        else
+                            fmt = "%b %d %h:%M";
+                    }
+                    else if (t < timeUnitSize.month)
+                        fmt = "%b %d";
+                    else if (t < timeUnitSize.year) {
+                        if (span < timeUnitSize.year)
+                            fmt = "%b";
+                        else
+                            fmt = "%b %y";
+                    }
+                    else
+                        fmt = "%y";
+                    
+                    return $.plot.formatDate(d, fmt, axisOptions.monthNames);
+                };
+            }
+            else {
+                // pretty rounding of base-10 numbers
+                var maxDec = axisOptions.tickDecimals;
+                var dec = -Math.floor(Math.log(delta) / Math.LN10);
+                if (maxDec != null && dec > maxDec)
+                    dec = maxDec;
+                
+                magn = Math.pow(10, -dec);
+                norm = delta / magn; // norm is between 1.0 and 10.0
+                
+                if (norm < 1.5)
+                    size = 1;
+                else if (norm < 3) {
+                    size = 2;
+                    // special case for 2.5, requires an extra decimal
+                    if (norm > 2.25 && (maxDec == null || dec + 1 <= maxDec)) {
+                        size = 2.5;
+                        ++dec;
+                    }
+                }
+                else if (norm < 7.5)
+                    size = 5;
+                else
+                    size = 10;
+
+                size *= magn;
+                
+                if (axisOptions.minTickSize != null && size < axisOptions.minTickSize)
+                    size = axisOptions.minTickSize;
+
+                if (axisOptions.tickSize != null)
+                    size = axisOptions.tickSize;
+                
+                axis.tickDecimals = Math.max(0, (maxDec != null) ? maxDec : dec);
+                
+                generator = function (axis) {
+                    var ticks = [];
+
+                    // spew out all possible ticks
+                    var start = floorInBase(axis.min, axis.tickSize),
+                        i = 0, v = Number.NaN, prev;
+                    do {
+                        prev = v;
+                        v = start + i * axis.tickSize;
+                        ticks.push({ v: v, label: axis.tickFormatter(v, axis) });
+                        ++i;
+                    } while (v < axis.max && v != prev);
+                    return ticks;
+                };
+
+                formatter = function (v, axis) {
+                    return v.toFixed(axis.tickDecimals);
+                };
+            }
+
+            axis.tickSize = unit ? [size, unit] : size;
+            axis.tickGenerator = generator;
+            if ($.isFunction(axisOptions.tickFormatter))
+                axis.tickFormatter = function (v, axis) { return "" + axisOptions.tickFormatter(v, axis); };
+            else
+                axis.tickFormatter = formatter;
+            if (axisOptions.labelWidth != null)
+                axis.labelWidth = axisOptions.labelWidth;
+            if (axisOptions.labelHeight != null)
+                axis.labelHeight = axisOptions.labelHeight;
+        }
+        
+        function setTicks(axis, axisOptions) {
+            axis.ticks = [];
+
+            if (!axis.used)
+                return;
+            
+            if (axisOptions.ticks == null)
+                axis.ticks = axis.tickGenerator(axis);
+            else if (typeof axisOptions.ticks == "number") {
+                if (axisOptions.ticks > 0)
+                    axis.ticks = axis.tickGenerator(axis);
+            }
+            else if (axisOptions.ticks) {
+                var ticks = axisOptions.ticks;
+
+                if ($.isFunction(ticks))
+                    // generate the ticks
+                    ticks = ticks({ min: axis.min, max: axis.max });
+                
+                // clean up the user-supplied ticks, copy them over
+                var i, v;
+                for (i = 0; i < ticks.length; ++i) {
+                    var label = null;
+                    var t = ticks[i];
+                    if (typeof t == "object") {
+                        v = t[0];
+                        if (t.length > 1)
+                            label = t[1];
+                    }
+                    else
+                        v = t;
+                    if (label == null)
+                        label = axis.tickFormatter(v, axis);
+                    axis.ticks[i] = { v: v, label: label };
+                }
+            }
+
+            if (axisOptions.autoscaleMargin != null && axis.ticks.length > 0) {
+                // snap to ticks
+                if (axisOptions.min == null)
+                    axis.min = Math.min(axis.min, axis.ticks[0].v);
+                if (axisOptions.max == null && axis.ticks.length > 1)
+                    axis.max = Math.min(axis.max, axis.ticks[axis.ticks.length - 1].v);
+            }
+        }
+        
+        function setSpacing() {
+            function measureXLabels(axis) {
+                // to avoid measuring the widths of the labels, we
+                // construct fixed-size boxes and put the labels inside
+                // them, we don't need the exact figures and the
+                // fixed-size box content is easy to center
+                if (axis.labelWidth == null)
+                    axis.labelWidth = canvasWidth / 6;
+
+                // measure x label heights
+                if (axis.labelHeight == null) {
+                    labels = [];
+                    for (i = 0; i < axis.ticks.length; ++i) {
+                        l = axis.ticks[i].label;
+                        if (l)
+                            labels.push('<div class="tickLabel" style="float:left;width:' + axis.labelWidth + 'px">' + l + '</div>');
+                    }
+                    
+                    axis.labelHeight = 0;
+                    if (labels.length > 0) {
+                        var dummyDiv = $('<div style="position:absolute;top:-10000px;width:10000px;font-size:smaller">'
+                                         + labels.join("") + '<div style="clear:left"></div></div>').appendTo(target);
+                        axis.labelHeight = dummyDiv.height();
+                        dummyDiv.remove();
+                    }
+                }
+            }
+            
+            function measureYLabels(axis) {
+                if (axis.labelWidth == null || axis.labelHeight == null) {
+                    var i, labels = [], l;
+                    // calculate y label dimensions
+                    for (i = 0; i < axis.ticks.length; ++i) {
+                        l = axis.ticks[i].label;
+                        if (l)
+                            labels.push('<div class="tickLabel">' + l + '</div>');
+                    }
+                    
+                    if (labels.length > 0) {
+                        var dummyDiv = $('<div style="position:absolute;top:-10000px;font-size:smaller">'
+                                         + labels.join("") + '</div>').appendTo(target);
+                        if (axis.labelWidth == null)
+                            axis.labelWidth = dummyDiv.width();
+                        if (axis.labelHeight == null)
+                            axis.labelHeight = dummyDiv.find("div").height();
+                        dummyDiv.remove();
+                    }
+                    
+                    if (axis.labelWidth == null)
+                        axis.labelWidth = 0;
+                    if (axis.labelHeight == null)
+                        axis.labelHeight = 0;
+                }
+            }
+            
+            measureXLabels(axes.xaxis);
+            measureYLabels(axes.yaxis);
+            measureXLabels(axes.x2axis);
+            measureYLabels(axes.y2axis);
+
+            // get the most space needed around the grid for things
+            // that may stick out
+            var maxOutset = options.grid.borderWidth;
+            for (i = 0; i < series.length; ++i)
+                maxOutset = Math.max(maxOutset, 2 * (series[i].points.radius + series[i].points.lineWidth/2));
+
+            plotOffset.left = plotOffset.right = plotOffset.top = plotOffset.bottom = maxOutset;
+
+            var margin = options.grid.labelMargin + options.grid.borderWidth;
+            
+            if (axes.xaxis.labelHeight > 0)
+                plotOffset.bottom = Math.max(maxOutset, axes.xaxis.labelHeight + margin);
+            if (axes.yaxis.labelWidth > 0)
+                plotOffset.left = Math.max(maxOutset, axes.yaxis.labelWidth + margin);
+
+            if (axes.x2axis.labelHeight > 0)
+                plotOffset.top = Math.max(maxOutset, axes.x2axis.labelHeight + margin);
+            
+            if (axes.y2axis.labelWidth > 0)
+                plotOffset.right = Math.max(maxOutset, axes.y2axis.labelWidth + margin);
+
+            plotWidth = canvasWidth - plotOffset.left - plotOffset.right;
+            plotHeight = canvasHeight - plotOffset.bottom - plotOffset.top;
+
+            // precompute how much the axis is scaling a point in canvas space
+            axes.xaxis.scale = plotWidth / (axes.xaxis.max - axes.xaxis.min);
+            axes.yaxis.scale = plotHeight / (axes.yaxis.max - axes.yaxis.min);
+            axes.x2axis.scale = plotWidth / (axes.x2axis.max - axes.x2axis.min);
+            axes.y2axis.scale = plotHeight / (axes.y2axis.max - axes.y2axis.min);
+        }
+        
+        function draw() {
+            drawGrid();
+            for (var i = 0; i < series.length; ++i) {
+                var s = series[i];
+                if (s.subseries)
+                    for (var j = 0; j < s.subseries.length; ++j)
+                        drawSeries(s.subseries[j]);
+                else
+                    drawSeries(s);
+            }
+        }
+
+        function extractRange(ranges, coord) {
+            var firstAxis = coord + "axis",
+                secondaryAxis = coord + "2axis",
+                axis, from, to, reverse;
+
+            if (ranges[firstAxis]) {
+                axis = axes[firstAxis];
+                from = ranges[firstAxis].from;
+                to = ranges[firstAxis].to;
+            }
+            else if (ranges[secondaryAxis]) {
+                axis = axes[secondaryAxis];
+                from = ranges[secondaryAxis].from;
+                to = ranges[secondaryAxis].to;
+            }
+            else {
+                // backwards-compat stuff - to be removed in future
+                axis = axes[firstAxis];
+                from = ranges[coord + "1"];
+                to = ranges[coord + "2"];
+            }
+
+            // auto-reverse as an added bonus
+            if (from != null && to != null && from > to)
+                return { from: to, to: from, axis: axis };
+            
+            return { from: from, to: to, axis: axis };
+        }
+        
+        function drawGrid() {
+            var i;
+            
+            ctx.save();
+            ctx.clearRect(0, 0, canvasWidth, canvasHeight);
+            ctx.translate(plotOffset.left, plotOffset.top);
+
+            // draw background, if any
+            if (options.grid.backgroundColor) {
+                ctx.fillStyle = getColorOrGradient(options.grid.backgroundColor, plotHeight, 0, "rgba(255, 255, 255, 0)");
+                ctx.fillRect(0, 0, plotWidth, plotHeight);
+            }
+
+            // draw markings
+            var markings = options.grid.markings;
+            if (markings) {
+                if ($.isFunction(markings))
+                    // xmin etc. are backwards-compatible, to be removed in future
+                    markings = markings({ xmin: axes.xaxis.min, xmax: axes.xaxis.max, ymin: axes.yaxis.min, ymax: axes.yaxis.max, xaxis: axes.xaxis, yaxis: axes.yaxis, x2axis: axes.x2axis, y2axis: axes.y2axis });
+
+                for (i = 0; i < markings.length; ++i) {
+                    var m = markings[i],
+                        xrange = extractRange(m, "x"),
+                        yrange = extractRange(m, "y");
+
+                    // fill in missing
+                    if (xrange.from == null)
+                        xrange.from = xrange.axis.min;
+                    if (xrange.to == null)
+                        xrange.to = xrange.axis.max;
+                    if (yrange.from == null)
+                        yrange.from = yrange.axis.min;
+                    if (yrange.to == null)
+                        yrange.to = yrange.axis.max;
+
+                    // clip
+                    if (xrange.to < xrange.axis.min || xrange.from > xrange.axis.max ||
+                        yrange.to < yrange.axis.min || yrange.from > yrange.axis.max)
+                        continue;
+
+                    xrange.from = Math.max(xrange.from, xrange.axis.min);
+                    xrange.to = Math.min(xrange.to, xrange.axis.max);
+                    yrange.from = Math.max(yrange.from, yrange.axis.min);
+                    yrange.to = Math.min(yrange.to, yrange.axis.max);
+
+                    if (xrange.from == xrange.to && yrange.from == yrange.to)
+                        continue;
+
+                    // then draw
+                    xrange.from = xrange.axis.p2c(xrange.from);
+                    xrange.to = xrange.axis.p2c(xrange.to);
+                    yrange.from = yrange.axis.p2c(yrange.from);
+                    yrange.to = yrange.axis.p2c(yrange.to);
+                    
+                    if (xrange.from == xrange.to || yrange.from == yrange.to) {
+                        // draw line
+                        ctx.strokeStyle = m.color || options.grid.markingsColor;
+                        ctx.beginPath();
+                        ctx.lineWidth = m.lineWidth || options.grid.markingsLineWidth;
+                        //ctx.moveTo(Math.floor(xrange.from), yrange.from);
+                        //ctx.lineTo(Math.floor(xrange.to), yrange.to);
+                        ctx.moveTo(xrange.from, yrange.from);
+                        ctx.lineTo(xrange.to, yrange.to);
+                        ctx.stroke();
+                    }
+                    else {
+                        // fill area
+                        ctx.fillStyle = m.color || options.grid.markingsColor;
+                        ctx.fillRect(xrange.from, yrange.to,
+                                     xrange.to - xrange.from,
+                                     yrange.from - yrange.to);
+                    }
+                }
+            }
+            
+            // draw the inner grid
+            ctx.lineWidth = 1;
+            ctx.strokeStyle = options.grid.tickColor;
+            ctx.beginPath();
+            var v, axis = axes.xaxis;
+            for (i = 0; i < axis.ticks.length; ++i) {
+                v = axis.ticks[i].v;
+                if (v <= axis.min || v >= axes.xaxis.max)
+                    continue;   // skip those lying on the axes
+
+                ctx.moveTo(Math.floor(axis.p2c(v)) + ctx.lineWidth/2, 0);
+                ctx.lineTo(Math.floor(axis.p2c(v)) + ctx.lineWidth/2, plotHeight);
+            }
+
+            axis = axes.yaxis;
+            for (i = 0; i < axis.ticks.length; ++i) {
+                v = axis.ticks[i].v;
+                if (v <= axis.min || v >= axis.max)
+                    continue;
+
+                ctx.moveTo(0, Math.floor(axis.p2c(v)) + ctx.lineWidth/2);
+                ctx.lineTo(plotWidth, Math.floor(axis.p2c(v)) + ctx.lineWidth/2);
+            }
+
+            axis = axes.x2axis;
+            for (i = 0; i < axis.ticks.length; ++i) {
+                v = axis.ticks[i].v;
+                if (v <= axis.min || v >= axis.max)
+                    continue;
+    
+                ctx.moveTo(Math.floor(axis.p2c(v)) + ctx.lineWidth/2, -5);
+                ctx.lineTo(Math.floor(axis.p2c(v)) + ctx.lineWidth/2, 5);
+            }
+
+            axis = axes.y2axis;
+            for (i = 0; i < axis.ticks.length; ++i) {
+                v = axis.ticks[i].v;
+                if (v <= axis.min || v >= axis.max)
+                    continue;
+
+                ctx.moveTo(plotWidth-5, Math.floor(axis.p2c(v)) + ctx.lineWidth/2);
+                ctx.lineTo(plotWidth+5, Math.floor(axis.p2c(v)) + ctx.lineWidth/2);
+            }
+            
+            ctx.stroke();
+            
+            if (options.grid.borderWidth) {
+                // draw border
+                var bw = options.grid.borderWidth;
+                ctx.lineWidth = bw;
+                ctx.strokeStyle = options.grid.borderColor;
+                ctx.strokeRect(-bw/2, -bw/2, plotWidth + bw, plotHeight + bw);
+            }
+
+            ctx.restore();
+        }
+        
+        function insertLabels() {
+            target.find(".tickLabels").remove();
+            
+            var html = ['<div class="tickLabels" style="font-size:smaller;color:' + options.grid.color + '">'];
+
+            function addLabels(axis, labelGenerator) {
+                for (var i = 0; i < axis.ticks.length; ++i) {
+                    var tick = axis.ticks[i];
+                    if (!tick.label || tick.v < axis.min || tick.v > axis.max)
+                        continue;
+                    html.push(labelGenerator(tick, axis));
+                }
+            }
+
+            var margin = options.grid.labelMargin + options.grid.borderWidth;
+            
+            addLabels(axes.xaxis, function (tick, axis) {
+                return '<div style="position:absolute;top:' + (plotOffset.top + plotHeight + margin) + 'px;left:' + Math.round(plotOffset.left + axis.p2c(tick.v) - axis.labelWidth/2) + 'px;width:' + axis.labelWidth + 'px;text-align:center" class="tickLabel">' + tick.label + "</div>";
+            });
+            
+            
+            addLabels(axes.yaxis, function (tick, axis) {
+                return '<div style="position:absolute;top:' + Math.round(plotOffset.top + axis.p2c(tick.v) - axis.labelHeight/2) + 'px;right:' + (plotOffset.right + plotWidth + margin) + 'px;width:' + axis.labelWidth + 'px;text-align:right" class="tickLabel">' + tick.label + "</div>";
+            });
+            
+            addLabels(axes.x2axis, function (tick, axis) {
+                return '<div style="position:absolute;bottom:' + (plotOffset.bottom + plotHeight + margin) + 'px;left:' + Math.round(plotOffset.left + axis.p2c(tick.v) - axis.labelWidth/2) + 'px;width:' + axis.labelWidth + 'px;text-align:center" class="tickLabel">' + tick.label + "</div>";
+            });
+            
+            addLabels(axes.y2axis, function (tick, axis) {
+                return '<div style="position:absolute;top:' + Math.round(plotOffset.top + axis.p2c(tick.v) - axis.labelHeight/2) + 'px;left:' + (plotOffset.left + plotWidth + margin) +'px;width:' + axis.labelWidth + 'px;text-align:left" class="tickLabel">' + tick.label + "</div>";
+            });
+
+            html.push('</div>');
+            
+            target.append(html.join(""));
+        }
+
+        function drawSeries(series) {
+            if (series.lines.show)
+                drawSeriesLines(series);
+            if (series.bars.show)
+                drawSeriesBars(series);
+            if (series.points.show)
+                drawSeriesPoints(series);
+        }
+        
+        function drawSeriesLines(series) {
+            function plotLine(datapoints, xoffset, yoffset, axisx, axisy) {
+                var points = datapoints.linespoints || datapoints.points,
+                    incr = datapoints.incr,
+                    prevx = null, prevy = null;
+                
+                ctx.beginPath();
+                for (var i = incr; i < points.length; i += incr) {
+                    var x1 = points[i - incr], y1 = points[i - incr + 1],
+                        x2 = points[i], y2 = points[i + 1];
+                    
+                    if (x1 == null || x2 == null)
+                        continue;
+
+                    // clip with ymin
+                    if (y1 <= y2 && y1 < axisy.min) {
+                        if (y2 < axisy.min)
+                            continue;   // line segment is outside
+                        // compute new intersection point
+                        x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
+                        y1 = axisy.min;
+                    }
+                    else if (y2 <= y1 && y2 < axisy.min) {
+                        if (y1 < axisy.min)
+                            continue;
+                        x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
+                        y2 = axisy.min;
+                    }
+
+                    // clip with ymax
+                    if (y1 >= y2 && y1 > axisy.max) {
+                        if (y2 > axisy.max)
+                            continue;
+                        x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
+                        y1 = axisy.max;
+                    }
+                    else if (y2 >= y1 && y2 > axisy.max) {
+                        if (y1 > axisy.max)
+                            continue;
+                        x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
+                        y2 = axisy.max;
+                    }
+
+                    // clip with xmin
+                    if (x1 <= x2 && x1 < axisx.min) {
+                        if (x2 < axisx.min)
+                            continue;
+                        y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
+                        x1 = axisx.min;
+                    }
+                    else if (x2 <= x1 && x2 < axisx.min) {
+                        if (x1 < axisx.min)
+                            continue;
+                        y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
+                        x2 = axisx.min;
+                    }
+
+                    // clip with xmax
+                    if (x1 >= x2 && x1 > axisx.max) {
+                        if (x2 > axisx.max)
+                            continue;
+                        y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
+                        x1 = axisx.max;
+                    }
+                    else if (x2 >= x1 && x2 > axisx.max) {
+                        if (x1 > axisx.max)
+                            continue;
+                        y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
+                        x2 = axisx.max;
+                    }
+
+                    if (x1 != prevx || y1 != prevy)
+                        ctx.moveTo(axisx.p2c(x1) + xoffset, axisy.p2c(y1) + yoffset);
+                    
+                    prevx = x2;
+                    prevy = y2;
+                    ctx.lineTo(axisx.p2c(x2) + xoffset, axisy.p2c(y2) + yoffset);
+                }
+                ctx.stroke();
+            }
+
+            function plotLineArea(datapoints, axisx, axisy) {
+                var points = datapoints.linespoints || datapoints.points,
+                    incr = datapoints.incr,
+                    bottom = Math.min(Math.max(0, axisy.min), axisy.max),
+                    top, lastX = 0, areaOpen = false;
+                
+                for (var i = incr; i < points.length; i += incr) {
+                    var x1 = points[i - incr], y1 = points[i - incr + 1],
+                        x2 = points[i], y2 = points[i + 1];
+                    
+                    if (areaOpen && x1 != null && x2 == null) {
+                        // close area
+                        ctx.lineTo(axisx.p2c(lastX), axisy.p2c(bottom));
+                        ctx.fill();
+                        areaOpen = false;
+                        continue;
+                    }
+
+                    if (x1 == null || x2 == null)
+                        continue;
+
+                    // clip x values
+                    
+                    // clip with xmin
+                    if (x1 <= x2 && x1 < axisx.min) {
+                        if (x2 < axisx.min)
+                            continue;
+                        y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
+                        x1 = axisx.min;
+                    }
+                    else if (x2 <= x1 && x2 < axisx.min) {
+                        if (x1 < axisx.min)
+                            continue;
+                        y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
+                        x2 = axisx.min;
+                    }
+
+                    // clip with xmax
+                    if (x1 >= x2 && x1 > axisx.max) {
+                        if (x2 > axisx.max)
+                            continue;
+                        y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
+                        x1 = axisx.max;
+                    }
+                    else if (x2 >= x1 && x2 > axisx.max) {
+                        if (x1 > axisx.max)
+                            continue;
+                        y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
+                        x2 = axisx.max;
+                    }
+
+                    if (!areaOpen) {
+                        // open area
+                        ctx.beginPath();
+                        ctx.moveTo(axisx.p2c(x1), axisy.p2c(bottom));
+                        areaOpen = true;
+                    }
+                    
+                    // now first check the case where both is outside
+                    if (y1 >= axisy.max && y2 >= axisy.max) {
+                        ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.max));
+                        ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.max));
+                        lastX = x2;
+                        continue;
+                    }
+                    else if (y1 <= axisy.min && y2 <= axisy.min) {
+                        ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.min));
+                        ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.min));
+                        lastX = x2;
+                        continue;
+                    }
+                    
+                    // else it's a bit more complicated, there might
+                    // be two rectangles and two triangles we need to fill
+                    // in; to find these keep track of the current x values
+                    var x1old = x1, x2old = x2;
+
+                    // and clip the y values, without shortcutting
+                    
+                    // clip with ymin
+                    if (y1 <= y2 && y1 < axisy.min && y2 >= axisy.min) {
+                        x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
+                        y1 = axisy.min;
+                    }
+                    else if (y2 <= y1 && y2 < axisy.min && y1 >= axisy.min) {
+                        x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
+                        y2 = axisy.min;
+                    }
+
+                    // clip with ymax
+                    if (y1 >= y2 && y1 > axisy.max && y2 <= axisy.max) {
+                        x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
+                        y1 = axisy.max;
+                    }
+                    else if (y2 >= y1 && y2 > axisy.max && y1 <= axisy.max) {
+                        x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
+                        y2 = axisy.max;
+                    }
+
+
+                    // if the x value was changed we got a rectangle
+                    // to fill
+                    if (x1 != x1old) {
+                        if (y1 <= axisy.min)
+                            top = axisy.min;
+                        else
+                            top = axisy.max;
+                        
+                        ctx.lineTo(axisx.p2c(x1old), axisy.p2c(top));
+                        ctx.lineTo(axisx.p2c(x1), axisy.p2c(top));
+                    }
+                    
+                    // fill the triangles
+                    ctx.lineTo(axisx.p2c(x1), axisy.p2c(y1));
+                    ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2));
+
+                    // fill the other rectangle if it's there
+                    if (x2 != x2old) {
+                        if (y2 <= axisy.min)
+                            top = axisy.min;
+                        else
+                            top = axisy.max;
+                        
+                        ctx.lineTo(axisx.p2c(x2), axisy.p2c(top));
+                        ctx.lineTo(axisx.p2c(x2old), axisy.p2c(top));
+                    }
+
+                    lastX = Math.max(x2, x2old);
+                }
+
+                if (areaOpen) {
+                    ctx.lineTo(axisx.p2c(lastX), axisy.p2c(bottom));
+                    ctx.fill();
+                }
+            }
+            
+            ctx.save();
+            ctx.translate(plotOffset.left, plotOffset.top);
+            ctx.lineJoin = "round";
+
+            var lw = series.lines.lineWidth,
+                sw = series.shadowSize;
+            // FIXME: consider another form of shadow when filling is turned on
+            if (lw > 0 && sw > 0) {
+                // draw shadow as a thick and thin line with transparency
+                ctx.lineWidth = sw;
+                ctx.strokeStyle = "rgba(0,0,0,0.1)";
+                var xoffset = 1;
+                plotLine(series.datapoints, xoffset, Math.sqrt((lw/2 + sw/2)*(lw/2 + sw/2) - xoffset*xoffset), series.xaxis, series.yaxis);
+                ctx.lineWidth = sw/2;
+                plotLine(series.datapoints, xoffset, Math.sqrt((lw/2 + sw/4)*(lw/2 + sw/4) - xoffset*xoffset), series.xaxis, series.yaxis);
+            }
+
+            ctx.lineWidth = lw;
+            ctx.strokeStyle = series.color;
+            var fillStyle = getFillStyle(series.lines, series.color, 0, plotHeight);
+            if (fillStyle) {
+                ctx.fillStyle = fillStyle;
+                plotLineArea(series.datapoints, series.xaxis, series.yaxis);
+            }
+
+            if (lw > 0)
+                plotLine(series.datapoints, 0, 0, series.xaxis, series.yaxis);
+            ctx.restore();
+        }
+
+        function drawSeriesPoints(series) {
+            function plotPoints(datapoints, radius, fillStyle, offset, circumference, axisx, axisy) {
+                var points = datapoints.points, incr = datapoints.incr;
+                
+                for (var i = 0; i < points.length; i += incr) {
+                    var x = points[i], y = points[i + 1];
+                    if (x == null || x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max)
+                        continue;
+                    
+                    ctx.beginPath();
+                    ctx.arc(axisx.p2c(x), axisy.p2c(y) + offset, radius, 0, circumference, true);
+                    if (fillStyle) {
+                        ctx.fillStyle = fillStyle;
+                        ctx.fill();
+                    }
+                    ctx.stroke();
+                }
+            }
+            
+            ctx.save();
+            ctx.translate(plotOffset.left, plotOffset.top);
+
+            var lw = series.lines.lineWidth,
+                sw = series.shadowSize,
+                radius = series.points.radius;
+            if (lw > 0 && sw > 0) {
+                // draw shadow in two steps
+                var w = sw / 2;
+                ctx.lineWidth = w;
+                ctx.strokeStyle = "rgba(0,0,0,0.1)";
+                plotPoints(series.datapoints, radius, null, w + w/2, 2 * Math.PI,
+                           series.xaxis, series.yaxis);
+
+                ctx.strokeStyle = "rgba(0,0,0,0.2)";
+                plotPoints(series.datapoints, radius, null, w/2, 2 * Math.PI,
+                           series.xaxis, series.yaxis);
+            }
+
+            ctx.lineWidth = lw;
+            ctx.strokeStyle = series.color;
+            plotPoints(series.datapoints, radius,
+                       getFillStyle(series.points, series.color), 0, 2 * Math.PI,
+                       series.xaxis, series.yaxis);
+            ctx.restore();
+        }
+
+        function drawBar(x, y, b, barLeft, barRight, offset, fillStyleCallback, axisx, axisy, c, horizontal) {
+            var left, right, bottom, top,
+                drawLeft, drawRight, drawTop, drawBottom,
+                tmp;
+
+            if (horizontal) {
+                drawBottom = drawRight = drawTop = true;
+                drawLeft = false;
+                left = b;
+                right = x;
+                top = y + barLeft;
+                bottom = y + barRight;
+
+                // account for negative bars
+                if (right < left) {
+                    tmp = right;
+                    right = left;
+                    left = tmp;
+                    drawLeft = true;
+                    drawRight = false;
+                }
+            }
+            else {
+                drawLeft = drawRight = drawTop = true;
+                drawBottom = false;
+                left = x + barLeft;
+                right = x + barRight;
+                bottom = b;
+                top = y;
+
+                // account for negative bars
+                if (top < bottom) {
+                    tmp = top;
+                    top = bottom;
+                    bottom = tmp;
+                    drawBottom = true;
+                    drawTop = false;
+                }
+            }
+           
+            // clip
+            if (right < axisx.min || left > axisx.max ||
+                top < axisy.min || bottom > axisy.max)
+                return;
+            
+            if (left < axisx.min) {
+                left = axisx.min;
+                drawLeft = false;
+            }
+
+            if (right > axisx.max) {
+                right = axisx.max;
+                drawRight = false;
+            }
+
+            if (bottom < axisy.min) {
+                bottom = axisy.min;
+                drawBottom = false;
+            }
+            
+            if (top > axisy.max) {
+                top = axisy.max;
+                drawTop = false;
+            }
+
+            left = axisx.p2c(left);
+            bottom = axisy.p2c(bottom);
+            right = axisx.p2c(right);
+            top = axisy.p2c(top);
+            
+            // fill the bar
+            if (fillStyleCallback) {
+                c.beginPath();
+                c.moveTo(left, bottom);
+                c.lineTo(left, top);
+                c.lineTo(right, top);
+                c.lineTo(right, bottom);
+                c.fillStyle = fillStyleCallback(bottom, top);
+                c.fill();
+            }
+
+            // draw outline
+            if (drawLeft || drawRight || drawTop || drawBottom) {
+                c.beginPath();
+
+                // FIXME: inline moveTo is buggy with excanvas
+                c.moveTo(left, bottom + offset);
+                if (drawLeft)
+                    c.lineTo(left, top + offset);
+                else
+                    c.moveTo(left, top + offset);
+                if (drawTop)
+                    c.lineTo(right, top + offset);
+                else
+                    c.moveTo(right, top + offset);
+                if (drawRight)
+                    c.lineTo(right, bottom + offset);
+                else
+                    c.moveTo(right, bottom + offset);
+                if (drawBottom)
+                    c.lineTo(left, bottom + offset);
+                else
+                    c.moveTo(left, bottom + offset);
+                c.stroke();
+            }
+        }
+        
+        function drawSeriesBars(series) {
+            function plotBars(datapoints, barLeft, barRight, offset, fillStyleCallback, axisx, axisy) {
+                var points = datapoints.points, incr = datapoints.incr;
+                
+                for (var i = 0; i < points.length; i += incr) {
+                    if (points[i] == null)
+                        continue;
+                    drawBar(points[i], points[i + 1], points[i + 2], barLeft, barRight, offset, fillStyleCallback, axisx, axisy, ctx, series.bars.horizontal);
+                }
+            }
+
+            ctx.save();
+            ctx.translate(plotOffset.left, plotOffset.top);
+
+            // FIXME: figure out a way to add shadows (for instance along the right edge)
+            ctx.lineWidth = series.bars.lineWidth;
+            ctx.strokeStyle = series.color;
+            var barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth/2;
+            var fillStyleCallback = series.bars.fill ? function (bottom, top) { return getFillStyle(series.bars, series.color, bottom, top); } : null;
+            plotBars(series.datapoints, barLeft, barLeft + series.bars.barWidth, 0, fillStyleCallback, series.xaxis, series.yaxis);
+            ctx.restore();
+        }
+
+        function getFillStyle(filloptions, seriesColor, bottom, top) {
+            var fill = filloptions.fill;
+            if (!fill)
+                return null;
+
+            if (filloptions.fillColor)
+                return getColorOrGradient(filloptions.fillColor, bottom, top, seriesColor);
+            
+            var c = parseColor(seriesColor);
+            c.a = typeof fill == "number" ? fill : 0.4;
+            c.normalize();
+            return c.toString();
+        }
+        
+        function insertLegend() {
+            target.find(".legend").remove();
+
+            if (!options.legend.show)
+                return;
+            
+            var fragments = [], rowStarted = false,
+                lf = options.legend.labelFormatter, s, label;
+            for (i = 0; i < series.length; ++i) {
+                s = series[i];
+                label = s.label;
+                if (!label)
+                    continue;
+                
+                if (i % options.legend.noColumns == 0) {
+                    if (rowStarted)
+                        fragments.push('</tr>');
+                    fragments.push('<tr>');
+                    rowStarted = true;
+                }
+
+                if (lf)
+                    label = lf(label, s);
+                
+                fragments.push(
+                    '<td class="legendColorBox"><div style="border:1px solid ' + options.legend.labelBoxBorderColor + ';padding:1px"><div style="width:4px;height:0;border:5px solid ' + s.color + ';overflow:hidden"></div></div></td>' +
+                    '<td class="legendLabel">' + label + '</td>');
+            }
+            if (rowStarted)
+                fragments.push('</tr>');
+            
+            if (fragments.length == 0)
+                return;
+
+            var table = '<table style="font-size:smaller;color:' + options.grid.color + '">' + fragments.join("") + '</table>';
+            if (options.legend.container != null)
+                $(options.legend.container).html(table);
+            else {
+                var pos = "",
+                    p = options.legend.position,
+                    m = options.legend.margin;
+                if (m[0] == null)
+                    m = [m, m];
+                if (p.charAt(0) == "n")
+                    pos += 'top:' + (m[1] + plotOffset.top) + 'px;';
+                else if (p.charAt(0) == "s")
+                    pos += 'bottom:' + (m[1] + plotOffset.bottom) + 'px;';
+                if (p.charAt(1) == "e")
+                    pos += 'right:' + (m[0] + plotOffset.right) + 'px;';
+                else if (p.charAt(1) == "w")
+                    pos += 'left:' + (m[0] + plotOffset.left) + 'px;';
+                var legend = $('<div class="legend">' + table.replace('style="', 'style="position:absolute;' + pos +';') + '</div>').appendTo(target);
+                if (options.legend.backgroundOpacity != 0.0) {
+                    // put in the transparent background
+                    // separately to avoid blended labels and
+                    // label boxes
+                    var c = options.legend.backgroundColor;
+                    if (c == null) {
+                        var tmp;
+                        if (options.grid.backgroundColor && typeof options.grid.backgroundColor == "string")
+                            tmp = options.grid.backgroundColor;
+                        else
+                            tmp = extractColor(legend);
+                        c = parseColor(tmp).adjust(null, null, null, 1).toString();
+                    }
+                    var div = legend.children();
+                    $('<div style="position:absolute;width:' + div.width() + 'px;height:' + div.height() + 'px;' + pos +'background-color:' + c + ';"> </div>').prependTo(legend).css('opacity', options.legend.backgroundOpacity);
+                }
+            }
+        }
+
+
+        // interactive features
+        
+        var lastMousePos = { pageX: null, pageY: null },
+            selection = {
+                first: { x: -1, y: -1}, second: { x: -1, y: -1},
+                show: false, active: false },
+            crosshair = { pos: { x: -1, y: -1 } },
+            highlights = [],
+            clickIsMouseUp = false,
+            redrawTimeout = null,
+            hoverTimeout = null;
+        
+        // Returns the data item the mouse is over, or null if none is found
+        function findNearbyItem(mouseX, mouseY, seriesFilter) {
+            var maxDistance = options.grid.mouseActiveRadius,
+                lowestDistance = maxDistance * maxDistance + 1,
+                item = null, foundPoint = false, i, j;
+
+            for (var i = 0; i < series.length; ++i) {
+                if (!seriesFilter(series[i]))
+                    continue;
+                
+                var s = series[i],
+                    axisx = s.xaxis,
+                    axisy = s.yaxis,
+                    points = s.datapoints.points,
+                    incr = s.datapoints.incr,
+                    mx = axisx.c2p(mouseX), // precompute some stuff to make the loop faster
+                    my = axisy.c2p(mouseY),
+                    maxx = maxDistance / axisx.scale,
+                    maxy = maxDistance / axisy.scale;
+
+                if (s.lines.show || s.points.show) {
+                    for (j = 0; j < points.length; j += incr) {
+                        var x = points[j], y = points[j + 1];
+                        if (x == null)
+                            continue;
+                        
+                        // For points and lines, the cursor must be within a
+                        // certain distance to the data point
+                        if (x - mx > maxx || x - mx < -maxx ||
+                            y - my > maxy || y - my < -maxy)
+                            continue;
+
+                        // We have to calculate distances in pixels, not in
+                        // data units, because the scales of the axes may be different
+                        var dx = Math.abs(axisx.p2c(x) - mouseX),
+                            dy = Math.abs(axisy.p2c(y) - mouseY),
+                            dist = dx * dx + dy * dy; // no idea in taking sqrt
+                        if (dist < lowestDistance) {
+                            lowestDistance = dist;
+                            item = [i, j / incr];
+                        }
+                    }
+                }
+                    
+                if (s.bars.show && !item) { // no other point can be nearby
+                    var barLeft = s.bars.align == "left" ? 0 : -s.bars.barWidth/2,
+                        barRight = barLeft + s.bars.barWidth;
+                    
+                    for (j = 0; j < points.length; j += incr) {
+                        var x = points[j], y = points[j + 1], b = points[j + 2];
+                        if (x == null)
+                            continue;
+  
+                        // for a bar graph, the cursor must be inside the bar
+                        if (series[i].bars.horizontal ? 
+                            (mx <= Math.max(b, x) && mx >= Math.min(b, x) && 
+                             my >= y + barLeft && my <= y + barRight) :
+                            (mx >= x + barLeft && mx <= x + barRight &&
+                             my >= Math.min(b, y) && my <= Math.max(b, y)))
+                                item = [i, j / incr];
+                    }
+                }
+            }
+
+            if (item) {
+                i = item[0];
+                j = item[1];
+                
+                return { datapoint: series[i].data[j],
+                         dataIndex: j,
+                         series: series[i],
+                         seriesIndex: i }
+            }
+            
+            return null;
+        }
+
+        function onMouseMove(ev) {
+            // FIXME: temp. work-around until jQuery bug 4398 is fixed
+            var e = ev || window.event;
+            if (e.pageX == null && e.clientX != null) {
+                var de = document.documentElement, b = document.body;
+                lastMousePos.pageX = e.clientX + (de && de.scrollLeft || b.scrollLeft || 0) - (de.clientLeft || 0);
+                lastMousePos.pageY = e.clientY + (de && de.scrollTop || b.scrollTop || 0) - (de.clientTop || 0);
+            }
+            else {
+                lastMousePos.pageX = e.pageX;
+                lastMousePos.pageY = e.pageY;
+            }
+            
+            if (options.grid.hoverable)
+                triggerClickHoverEvent("plothover", lastMousePos,
+                                       function (s) { return s["hoverable"] != false; });
+
+            if (options.crosshair.mode != null) {
+                if (!selection.active) {
+                    setPositionFromEvent(crosshair.pos, lastMousePos);
+                    triggerRedrawOverlay();
+                }
+                else
+                    crosshair.pos.x = -1; // hide the crosshair while selecting
+            }
+
+            if (selection.active) {
+                target.trigger("plotselecting", [ selectionIsSane() ? getSelectionForEvent() : null ]);
+
+                updateSelection(lastMousePos);
+            }
+        }
+        
+        function onMouseDown(e) {
+            if (e.which != 1)  // only accept left-click
+                return;
+            
+            // cancel out any text selections
+            document.body.focus();
+
+            // prevent text selection and drag in old-school browsers
+            if (document.onselectstart !== undefined && workarounds.onselectstart == null) {
+                workarounds.onselectstart = document.onselectstart;
+                document.onselectstart = function () { return false; };
+            }
+            if (document.ondrag !== undefined && workarounds.ondrag == null) {
+                workarounds.ondrag = document.ondrag;
+                document.ondrag = function () { return false; };
+            }
+            
+            setSelectionPos(selection.first, e);
+                
+            lastMousePos.pageX = null;
+            selection.active = true;
+            $(document).one("mouseup", onSelectionMouseUp);
+        }
+
+        function onMouseOut(ev) {
+            if (options.crosshair.mode != null && crosshair.pos.x != -1) {
+                crosshair.pos.x = -1;
+                triggerRedrawOverlay();
+            }
+        }
+        
+        function onClick(e) {
+            if (clickIsMouseUp) {
+                clickIsMouseUp = false;
+                return;
+            }
+
+            triggerClickHoverEvent("plotclick", e,
+                                   function (s) { return s["clickable"] != false; });
+        }
+
+        /*
+        function userPositionInCanvasSpace(pos) {
+            return { x: parseInt(pos.x != null ? axes.xaxis.p2c(pos.x) : axes.x2axis.p2c(pos.x2)),
+                     y: parseInt(pos.y != null ? axes.yaxis.p2c(pos.y) : axes.y2axis.p2c(pos.y2)) };
+        }
+        
+        function positionInDivSpace(pos) {
+            var cpos = userPositionInCanvasSpace(pos);
+            return { x: cpos.x + plotOffset.left,
+                     y: cpos.y + plotOffset.top };
+        }*/
+        
+        // trigger click or hover event (they send the same parameters
+        // so we share their code)
+        function triggerClickHoverEvent(eventname, event, seriesFilter) {
+            var offset = eventHolder.offset(),
+                pos = { pageX: event.pageX, pageY: event.pageY },
+                canvasX = event.pageX - offset.left - plotOffset.left,
+                canvasY = event.pageY - offset.top - plotOffset.top;
+
+            if (axes.xaxis.used)
+                pos.x = axes.xaxis.c2p(canvasX);
+            if (axes.yaxis.used)
+                pos.y = axes.yaxis.c2p(canvasY);
+            if (axes.x2axis.used)
+                pos.x2 = axes.x2axis.c2p(canvasX);
+            if (axes.y2axis.used)
+                pos.y2 = axes.y2axis.c2p(canvasY);
+
+            var item = findNearbyItem(canvasX, canvasY, seriesFilter);
+
+            if (item) {
+                // fill in mouse pos for any listeners out there
+                item.pageX = parseInt(item.series.xaxis.p2c(item.datapoint[0]) + offset.left + plotOffset.left);
+                item.pageY = parseInt(item.series.yaxis.p2c(item.datapoint[1]) + offset.top + plotOffset.top);
+            }
+
+            if (options.grid.autoHighlight) {
+                // clear auto-highlights
+                for (var i = 0; i < highlights.length; ++i) {
+                    var h = highlights[i];
+                    if (h.auto == eventname &&
+                        !(item && h.series == item.series && h.point == item.datapoint))
+                        unhighlight(h.series, h.point);
+                }
+                
+                if (item)
+                    highlight(item.series, item.datapoint, eventname);
+            }
+            
+            target.trigger(eventname, [ pos, item ]);
+        }
+
+        function triggerRedrawOverlay() {
+            if (!redrawTimeout)
+                redrawTimeout = setTimeout(redrawOverlay, 30);
+        }
+
+        function redrawOverlay() {
+            redrawTimeout = null;
+
+            // redraw highlights
+            octx.save();
+            octx.clearRect(0, 0, canvasWidth, canvasHeight);
+            octx.translate(plotOffset.left, plotOffset.top);
+            
+            var i, hi;
+            for (i = 0; i < highlights.length; ++i) {
+                hi = highlights[i];
+
+                if (hi.series.bars.show)
+                    drawBarHighlight(hi.series, hi.point);
+                else
+                    drawPointHighlight(hi.series, hi.point);
+            }
+
+            // redraw selection
+            if (selection.show && selectionIsSane()) {
+                octx.strokeStyle = parseColor(options.selection.color).scale(null, null, null, 0.8).toString();
+                octx.lineWidth = 1;
+                ctx.lineJoin = "round";
+                octx.fillStyle = parseColor(options.selection.color).scale(null, null, null, 0.4).toString();
+                
+                var x = Math.min(selection.first.x, selection.second.x),
+                    y = Math.min(selection.first.y, selection.second.y),
+                    w = Math.abs(selection.second.x - selection.first.x),
+                    h = Math.abs(selection.second.y - selection.first.y);
+                
+                octx.fillRect(x, y, w, h);
+                octx.strokeRect(x, y, w, h);
+            }
+
+            // redraw crosshair
+            var pos = crosshair.pos, mode = options.crosshair.mode;
+            if (mode != null && pos.x != -1) {
+                octx.strokeStyle = parseColor(options.crosshair.color).scale(null, null, null, 0.8).toString();
+                octx.lineWidth = 1;
+                ctx.lineJoin = "round";
+
+                octx.beginPath();
+                if (mode.indexOf("x") != -1) {
+                    octx.moveTo(pos.x, 0);
+                    octx.lineTo(pos.x, plotHeight);
+                }
+                if (mode.indexOf("y") != -1) {
+                    octx.moveTo(0, pos.y);
+                    octx.lineTo(plotWidth, pos.y);
+                }
+                octx.stroke();
+                
+            }
+            octx.restore();
+        }
+        
+        function highlight(s, point, auto) {
+            if (typeof s == "number")
+                s = series[s];
+
+            if (typeof point == "number")
+                point = s.data[point];
+
+            var i = indexOfHighlight(s, point);
+            if (i == -1) {
+                highlights.push({ series: s, point: point, auto: auto });
+
+                triggerRedrawOverlay();
+            }
+            else if (!auto)
+                highlights[i].auto = false;
+        }
+            
+        function unhighlight(s, point) {
+            if (typeof s == "number")
+                s = series[s];
+
+            if (typeof point == "number")
+                point = s.data[point];
+
+            var i = indexOfHighlight(s, point);
+            if (i != -1) {
+                highlights.splice(i, 1);
+
+                triggerRedrawOverlay();
+            }
+        }
+        
+        function indexOfHighlight(s, p) {
+            for (var i = 0; i < highlights.length; ++i) {
+                var h = highlights[i];
+                if (h.series == s && h.point[0] == p[0]
+                    && h.point[1] == p[1])
+                    return i;
+            }
+            return -1;
+        }
+        
+        function drawPointHighlight(series, point) {
+            var x = point[0], y = point[1],
+                axisx = series.xaxis, axisy = series.yaxis;
+            
+            if (x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max)
+                return;
+            
+            var pointRadius = series.points.radius + series.points.lineWidth / 2;
+            octx.lineWidth = pointRadius;
+            octx.strokeStyle = parseColor(series.color).scale(1, 1, 1, 0.5).toString();
+            var radius = 1.5 * pointRadius;
+            octx.beginPath();
+            octx.arc(axisx.p2c(x), axisy.p2c(y), radius, 0, 2 * Math.PI, true);
+            octx.stroke();
+        }
+
+        function drawBarHighlight(series, point) {
+            octx.lineWidth = series.bars.lineWidth;
+            octx.strokeStyle = parseColor(series.color).scale(1, 1, 1, 0.5).toString();
+            var fillStyle = parseColor(series.color).scale(1, 1, 1, 0.5).toString();
+            var barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth/2;
+            drawBar(point[0], point[1], point[2] || 0, barLeft, barLeft + series.bars.barWidth,
+                    0, function () { return fillStyle; }, series.xaxis, series.yaxis, octx, series.bars.horizontal);
+        }
+
+        function setPositionFromEvent(pos, e) {
+            var offset = eventHolder.offset();
+            pos.x = clamp(0, e.pageX - offset.left - plotOffset.left, plotWidth);
+            pos.y = clamp(0, e.pageY - offset.top - plotOffset.top, plotHeight);
+        }
+
+        function setCrosshair(pos) {
+            if (pos == null)
+                crosshair.pos.x = -1;
+            else {
+                crosshair.pos.x = clamp(0, pos.x != null ? axes.xaxis.p2c(pos.x) : axes.x2axis.p2c(pos.x2), plotWidth);
+                crosshair.pos.y = clamp(0, pos.y != null ? axes.yaxis.p2c(pos.y) : axes.y2axis.p2c(pos.y2), plotHeight);
+            }
+            triggerRedrawOverlay();
+        }
+
+        function getSelectionForEvent() {
+            var x1 = Math.min(selection.first.x, selection.second.x),
+                x2 = Math.max(selection.first.x, selection.second.x),
+                y1 = Math.max(selection.first.y, selection.second.y),
+                y2 = Math.min(selection.first.y, selection.second.y);
+
+            var r = {};
+            if (axes.xaxis.used)
+                r.xaxis = { from: axes.xaxis.c2p(x1), to: axes.xaxis.c2p(x2) };
+            if (axes.x2axis.used)
+                r.x2axis = { from: axes.x2axis.c2p(x1), to: axes.x2axis.c2p(x2) };
+            if (axes.yaxis.used)
+                r.yaxis = { from: axes.yaxis.c2p(y1), to: axes.yaxis.c2p(y2) };
+            if (axes.y2axis.used)
+                r.y2axis = { from: axes.y2axis.c2p(y1), to: axes.y2axis.c2p(y2) };
+            return r;
+        }
+        
+        function triggerSelectedEvent() {
+            var r = getSelectionForEvent();
+            
+            target.trigger("plotselected", [ r ]);
+
+            // backwards-compat stuff, to be removed in future
+            if (axes.xaxis.used && axes.yaxis.used)
+                target.trigger("selected", [ { x1: r.xaxis.from, y1: r.yaxis.from, x2: r.xaxis.to, y2: r.yaxis.to } ]);
+        }
+        
+        function onSelectionMouseUp(e) {
+            // revert drag stuff for old-school browsers
+            if (document.onselectstart !== undefined)
+                document.onselectstart = workarounds.onselectstart;
+            if (document.ondrag !== undefined)
+                document.ondrag = workarounds.ondrag;
+            
+            // no more draggy-dee-drag
+            selection.active = false;
+            updateSelection(e);
+            
+            if (selectionIsSane()) {
+                triggerSelectedEvent();
+                clickIsMouseUp = true;
+            }
+            else {
+                // this counts as a clear
+                target.trigger("plotunselected", [ ]);
+                target.trigger("plotselecting", [ null ]);
+            }
+            
+            return false;
+        }
+
+        function setSelectionPos(pos, e) {
+            setPositionFromEvent(pos, e);
+            
+            if (options.selection.mode == "y") {
+                if (pos == selection.first)
+                    pos.x = 0;
+                else
+                    pos.x = plotWidth;
+            }
+
+            if (options.selection.mode == "x") {
+                if (pos == selection.first)
+                    pos.y = 0;
+                else
+                    pos.y = plotHeight;
+            }
+        }
+
+        function updateSelection(pos) {
+            if (pos.pageX == null)
+                return;
+
+            setSelectionPos(selection.second, pos);
+            if (selectionIsSane()) {
+                selection.show = true;
+                triggerRedrawOverlay();
+            }
+            else
+                clearSelection(true);
+        }
+
+        function clearSelection(preventEvent) {
+            if (selection.show) {
+                selection.show = false;
+                triggerRedrawOverlay();
+                if (!preventEvent)
+                    target.trigger("plotunselected", [ ]);
+            }
+        }
+
+        function setSelection(ranges, preventEvent) {
+            var range;
+            
+            if (options.selection.mode == "y") {
+                selection.first.x = 0;
+                selection.second.x = plotWidth;
+            }
+            else {
+                range = extractRange(ranges, "x");
+                
+                selection.first.x = range.axis.p2c(range.from);
+                selection.second.x = range.axis.p2c(range.to);
+            }
+            
+            if (options.selection.mode == "x") {
+                selection.first.y = 0;
+                selection.second.y = plotHeight;
+            }
+            else {
+                range = extractRange(ranges, "y");
+                
+                selection.first.y = range.axis.p2c(range.from);
+                selection.second.y = range.axis.p2c(range.to);
+            }
+
+            selection.show = true;
+            triggerRedrawOverlay();
+            if (!preventEvent)
+                triggerSelectedEvent();
+        }
+        
+        function selectionIsSane() {
+            var minSize = 5;
+            return Math.abs(selection.second.x - selection.first.x) >= minSize &&
+                Math.abs(selection.second.y - selection.first.y) >= minSize;
+        }
+        
+        function getColorOrGradient(spec, bottom, top, defaultColor) {
+            if (typeof spec == "string")
+                return spec;
+            else {
+                // assume this is a gradient spec; IE currently only
+                // supports a simple vertical gradient properly, so that's
+                // what we support too
+                var gradient = ctx.createLinearGradient(0, top, 0, bottom);
+                
+                for (var i = 0, l = spec.colors.length; i < l; ++i) {
+                    var c = spec.colors[i];
+                    gradient.addColorStop(i / (l - 1), typeof c == "string" ? c : parseColor(defaultColor).scale(c.brightness, c.brightness, c.brightness, c.opacity));
+                }
+                
+                return gradient;
+            }
+        }
+    }
+    
+    $.plot = function(target, data, options) {
+        var plot = new Plot(target, data, options);
+        /*var t0 = new Date();     
+        var t1 = new Date();
+        var tstr = "time used (msecs): " + (t1.getTime() - t0.getTime())
+        if (window.console)
+            console.log(tstr);
+        else
+            alert(tstr);*/
+        return plot;
+    };
+
+    // returns a string with the date d formatted according to fmt
+    $.plot.formatDate = function(d, fmt, monthNames) {
+        var leftPad = function(n) {
+            n = "" + n;
+            return n.length == 1 ? "0" + n : n;
+        };
+        
+        var r = [];
+        var escape = false;
+        if (monthNames == null)
+            monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
+        for (var i = 0; i < fmt.length; ++i) {
+            var c = fmt.charAt(i);
+            
+            if (escape) {
+                switch (c) {
+                case 'h': c = "" + d.getUTCHours(); break;
+                case 'H': c = leftPad(d.getUTCHours()); break;
+                case 'M': c = leftPad(d.getUTCMinutes()); break;
+                case 'S': c = leftPad(d.getUTCSeconds()); break;
+                case 'd': c = "" + d.getUTCDate(); break;
+                case 'm': c = "" + (d.getUTCMonth() + 1); break;
+                case 'y': c = "" + d.getUTCFullYear(); break;
+                case 'b': c = "" + monthNames[d.getUTCMonth()]; break;
+                }
+                r.push(c);
+                escape = false;
+            }
+            else {
+                if (c == "%")
+                    escape = true;
+                else
+                    r.push(c);
+            }
+        }
+        return r.join("");
+    };
+    
+    // round to nearby lower multiple of base
+    function floorInBase(n, base) {
+        return base * Math.floor(n / base);
+    }
+    
+    function clamp(min, value, max) {
+        if (value < min)
+            return min;
+        else if (value > max)
+            return max;
+        else
+            return value;
+    }
+    
+    // color helpers, inspiration from the jquery color animation
+    // plugin by John Resig
+    function Color (r, g, b, a) {
+       
+        var rgba = ['r','g','b','a'];
+        var x = 4; //rgba.length
+       
+        while (-1<--x) {
+            this[rgba[x]] = arguments[x] || ((x==3) ? 1.0 : 0);
+        }
+       
+        this.toString = function() {
+            if (this.a >= 1.0) {
+                return "rgb("+[this.r,this.g,this.b].join(",")+")";
+            } else {
+                return "rgba("+[this.r,this.g,this.b,this.a].join(",")+")";
+            }
+        };
+
+        this.scale = function(rf, gf, bf, af) {
+            x = 4; //rgba.length
+            while (-1<--x) {
+                if (arguments[x] != null)
+                    this[rgba[x]] *= arguments[x];
+            }
+            return this.normalize();
+        };
+
+        this.adjust = function(rd, gd, bd, ad) {
+            x = 4; //rgba.length
+            while (-1<--x) {
+                if (arguments[x] != null)
+                    this[rgba[x]] += arguments[x];
+            }
+            return this.normalize();
+        };
+
+        this.clone = function() {
+            return new Color(this.r, this.b, this.g, this.a);
+        };
+
+        var limit = function(val,minVal,maxVal) {
+            return Math.max(Math.min(val, maxVal), minVal);
+        };
+
+        this.normalize = function() {
+            this.r = clamp(0, parseInt(this.r), 255);
+            this.g = clamp(0, parseInt(this.g), 255);
+            this.b = clamp(0, parseInt(this.b), 255);
+            this.a = clamp(0, this.a, 1);
+            return this;
+        };
+
+        this.normalize();
+    }
+    
+    var lookupColors = {
+        aqua:[0,255,255],
+        azure:[240,255,255],
+        beige:[245,245,220],
+        black:[0,0,0],
+        blue:[0,0,255],
+        brown:[165,42,42],
+        cyan:[0,255,255],
+        darkblue:[0,0,139],
+        darkcyan:[0,139,139],
+        darkgrey:[169,169,169],
+        darkgreen:[0,100,0],
+        darkkhaki:[189,183,107],
+        darkmagenta:[139,0,139],
+        darkolivegreen:[85,107,47],
+        darkorange:[255,140,0],
+        darkorchid:[153,50,204],
+        darkred:[139,0,0],
+        darksalmon:[233,150,122],
+        darkviolet:[148,0,211],
+        fuchsia:[255,0,255],
+        gold:[255,215,0],
+        green:[0,128,0],
+        indigo:[75,0,130],
+        khaki:[240,230,140],
+        lightblue:[173,216,230],
+        lightcyan:[224,255,255],
+        lightgreen:[144,238,144],
+        lightgrey:[211,211,211],
+        lightpink:[255,182,193],
+        lightyellow:[255,255,224],
+        lime:[0,255,0],
+        magenta:[255,0,255],
+        maroon:[128,0,0],
+        navy:[0,0,128],
+        olive:[128,128,0],
+        orange:[255,165,0],
+        pink:[255,192,203],
+        purple:[128,0,128],
+        violet:[128,0,128],
+        red:[255,0,0],
+        silver:[192,192,192],
+        white:[255,255,255],
+        yellow:[255,255,0]
+    };    
+
+    function extractColor(element) {
+        var color, elem = element;
+        do {
+            color = elem.css("background-color").toLowerCase();
+            // keep going until we find an element that has color, or
+            // we hit the body
+            if (color != '' && color != 'transparent')
+                break;
+            elem = elem.parent();
+        } while (!$.nodeName(elem.get(0), "body"));
+
+        // catch Safari's way of signalling transparent
+        if (color == "rgba(0, 0, 0, 0)")
+            return "transparent";
+        
+        return color;
+    }
+    
+    // parse string, returns Color
+    function parseColor(str) {
+        var result;
+
+        // Look for rgb(num,num,num)
+        if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(str))
+            return new Color(parseInt(result[1], 10), parseInt(result[2], 10), parseInt(result[3], 10));
+        
+        // Look for rgba(num,num,num,num)
+        if (result = /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))
+            return new Color(parseInt(result[1], 10), parseInt(result[2], 10), parseInt(result[3], 10), parseFloat(result[4]));
+            
+        // Look for rgb(num%,num%,num%)
+        if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(str))
+            return new Color(parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55);
+
+        // Look for rgba(num%,num%,num%,num)
+        if (result = /rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))
+            return new Color(parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55, parseFloat(result[4]));
+        
+        // Look for #a0b1c2
+        if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(str))
+            return new Color(parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16));
+
+        // Look for #fff
+        if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(str))
+            return new Color(parseInt(result[1]+result[1], 16), parseInt(result[2]+result[2], 16), parseInt(result[3]+result[3], 16));
+
+        // Otherwise, we're most likely dealing with a named color
+        var name = $.trim(str).toLowerCase();
+        if (name == "transparent")
+            return new Color(255, 255, 255, 0);
+        else {
+            result = lookupColors[name];
+            return new Color(result[0], result[1], result[2]);
+        }
+    }
+        
+})(jQuery);
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/jquery.flot.min.js b/forum/modules/template_loader.py/forum/skins/default/media/js/jquery.flot.min.js
new file mode 100644 (file)
index 0000000..31f465b
--- /dev/null
@@ -0,0 +1 @@
+(function(){jQuery.color={};jQuery.color.make=function(G,H,J,I){var A={};A.r=G||0;A.g=H||0;A.b=J||0;A.a=I!=null?I:1;A.add=function(C,D){for(var E=0;E<C.length;++E){A[C.charAt(E)]+=D}return A.normalize()};A.scale=function(C,D){for(var E=0;E<C.length;++E){A[C.charAt(E)]*=D}return A.normalize()};A.toString=function(){if(A.a>=1){return"rgb("+[A.r,A.g,A.b].join(",")+")"}else{return"rgba("+[A.r,A.g,A.b,A.a].join(",")+")"}};A.normalize=function(){function C(E,D,F){return D<E?E:(D>F?F:D)}A.r=C(0,parseInt(A.r),255);A.g=C(0,parseInt(A.g),255);A.b=C(0,parseInt(A.b),255);A.a=C(0,A.a,1);return A};A.clone=function(){return jQuery.color.make(A.r,A.b,A.g,A.a)};return A.normalize()};jQuery.color.extract=function(E,F){var A;do{A=E.css(F).toLowerCase();if(A!=""&&A!="transparent"){break}E=E.parent()}while(!jQuery.nodeName(E.get(0),"body"));if(A=="rgba(0, 0, 0, 0)"){A="transparent"}return jQuery.color.parse(A)};jQuery.color.parse=function(A){var F,H=jQuery.color.make;if(F=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(A)){return H(parseInt(F[1],10),parseInt(F[2],10),parseInt(F[3],10))}if(F=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(A)){return H(parseInt(F[1],10),parseInt(F[2],10),parseInt(F[3],10),parseFloat(F[4]))}if(F=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(A)){return H(parseFloat(F[1])*2.55,parseFloat(F[2])*2.55,parseFloat(F[3])*2.55)}if(F=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(A)){return H(parseFloat(F[1])*2.55,parseFloat(F[2])*2.55,parseFloat(F[3])*2.55,parseFloat(F[4]))}if(F=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(A)){return H(parseInt(F[1],16),parseInt(F[2],16),parseInt(F[3],16))}if(F=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(A)){return H(parseInt(F[1]+F[1],16),parseInt(F[2]+F[2],16),parseInt(F[3]+F[3],16))}var G=jQuery.trim(A).toLowerCase();if(G=="transparent"){return H(255,255,255,0)}else{F=B[G];return H(F[0],F[1],F[2])}};var B={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})();(function(C){function B(l,W,X,E){var O=[],g={colors:["#edc240","#afd8f8","#cb4b4b","#4da74d","#9440ed"],legend:{show:true,noColumns:1,labelFormatter:null,labelBoxBorderColor:"#ccc",container:null,position:"ne",margin:5,backgroundColor:null,backgroundOpacity:0.85},xaxis:{mode:null,transform:null,inverseTransform:null,min:null,max:null,autoscaleMargin:null,ticks:null,tickFormatter:null,labelWidth:null,labelHeight:null,tickDecimals:null,tickSize:null,minTickSize:null,monthNames:null,timeformat:null,twelveHourClock:false},yaxis:{autoscaleMargin:0.02},x2axis:{autoscaleMargin:null},y2axis:{autoscaleMargin:0.02},series:{points:{show:false,radius:3,lineWidth:2,fill:true,fillColor:"#ffffff"},lines:{lineWidth:2,fill:false,fillColor:null,steps:false},bars:{show:false,lineWidth:2,barWidth:1,fill:true,fillColor:null,align:"left",horizontal:false},shadowSize:3},grid:{show:true,aboveData:false,color:"#545454",backgroundColor:null,tickColor:"rgba(0,0,0,0.15)",labelMargin:5,borderWidth:2,borderColor:null,markings:null,markingsColor:"#f4f4f4",markingsLineWidth:2,clickable:false,hoverable:false,autoHighlight:true,mouseActiveRadius:10},hooks:{}},P=null,AC=null,AD=null,Y=null,AJ=null,s={xaxis:{},yaxis:{},x2axis:{},y2axis:{}},e={left:0,right:0,top:0,bottom:0},y=0,Q=0,I=0,t=0,L={processOptions:[],processRawData:[],processDatapoints:[],draw:[],bindEvents:[],drawOverlay:[]},G=this;G.setData=f;G.setupGrid=k;G.draw=AH;G.getPlaceholder=function(){return l};G.getCanvas=function(){return P};G.getPlotOffset=function(){return e};G.width=function(){return I};G.height=function(){return t};G.offset=function(){var AK=AD.offset();AK.left+=e.left;AK.top+=e.top;return AK};G.getData=function(){return O};G.getAxes=function(){return s};G.getOptions=function(){return g};G.highlight=AE;G.unhighlight=x;G.triggerRedrawOverlay=q;G.pointOffset=function(AK){return{left:parseInt(T(AK,"xaxis").p2c(+AK.x)+e.left),top:parseInt(T(AK,"yaxis").p2c(+AK.y)+e.top)}};G.hooks=L;b(G);r(X);c();f(W);k();AH();AG();function Z(AM,AK){AK=[G].concat(AK);for(var AL=0;AL<AM.length;++AL){AM[AL].apply(this,AK)}}function b(){for(var AK=0;AK<E.length;++AK){var AL=E[AK];AL.init(G);if(AL.options){C.extend(true,g,AL.options)}}}function r(AK){C.extend(true,g,AK);if(g.grid.borderColor==null){g.grid.borderColor=g.grid.color}if(g.xaxis.noTicks&&g.xaxis.ticks==null){g.xaxis.ticks=g.xaxis.noTicks}if(g.yaxis.noTicks&&g.yaxis.ticks==null){g.yaxis.ticks=g.yaxis.noTicks}if(g.grid.coloredAreas){g.grid.markings=g.grid.coloredAreas}if(g.grid.coloredAreasColor){g.grid.markingsColor=g.grid.coloredAreasColor}if(g.lines){C.extend(true,g.series.lines,g.lines)}if(g.points){C.extend(true,g.series.points,g.points)}if(g.bars){C.extend(true,g.series.bars,g.bars)}if(g.shadowSize){g.series.shadowSize=g.shadowSize}for(var AL in L){if(g.hooks[AL]&&g.hooks[AL].length){L[AL]=L[AL].concat(g.hooks[AL])}}Z(L.processOptions,[g])}function f(AK){O=M(AK);U();m()}function M(AN){var AL=[];for(var AK=0;AK<AN.length;++AK){var AM=C.extend(true,{},g.series);if(AN[AK].data){AM.data=AN[AK].data;delete AN[AK].data;C.extend(true,AM,AN[AK]);AN[AK].data=AM.data}else{AM.data=AN[AK]}AL.push(AM)}return AL}function T(AM,AK){var AL=AM[AK];if(!AL||AL==1){return s[AK]}if(typeof AL=="number"){return s[AK.charAt(0)+AL+AK.slice(1)]}return AL}function U(){var AP;var AV=O.length,AK=[],AN=[];for(AP=0;AP<O.length;++AP){var AS=O[AP].color;if(AS!=null){--AV;if(typeof AS=="number"){AN.push(AS)}else{AK.push(C.color.parse(O[AP].color))}}}for(AP=0;AP<AN.length;++AP){AV=Math.max(AV,AN[AP]+1)}var AL=[],AO=0;AP=0;while(AL.length<AV){var AR;if(g.colors.length==AP){AR=C.color.make(100,100,100)}else{AR=C.color.parse(g.colors[AP])}var AM=AO%2==1?-1:1;AR.scale("rgb",1+AM*Math.ceil(AO/2)*0.2);AL.push(AR);++AP;if(AP>=g.colors.length){AP=0;++AO}}var AQ=0,AW;for(AP=0;AP<O.length;++AP){AW=O[AP];if(AW.color==null){AW.color=AL[AQ].toString();++AQ}else{if(typeof AW.color=="number"){AW.color=AL[AW.color].toString()}}if(AW.lines.show==null){var AU,AT=true;for(AU in AW){if(AW[AU].show){AT=false;break}}if(AT){AW.lines.show=true}}AW.xaxis=T(AW,"xaxis");AW.yaxis=T(AW,"yaxis")}}function m(){var AW=Number.POSITIVE_INFINITY,AQ=Number.NEGATIVE_INFINITY,Ac,Aa,AZ,AV,AL,AR,Ab,AX,AP,AO,AK,Ai,Af,AT;for(AK in s){s[AK].datamin=AW;s[AK].datamax=AQ;s[AK].used=false}function AN(Al,Ak,Aj){if(Ak<Al.datamin){Al.datamin=Ak}if(Aj>Al.datamax){Al.datamax=Aj}}for(Ac=0;Ac<O.length;++Ac){AR=O[Ac];AR.datapoints={points:[]};Z(L.processRawData,[AR,AR.data,AR.datapoints])}for(Ac=0;Ac<O.length;++Ac){AR=O[Ac];var Ah=AR.data,Ae=AR.datapoints.format;if(!Ae){Ae=[];Ae.push({x:true,number:true,required:true});Ae.push({y:true,number:true,required:true});if(AR.bars.show){Ae.push({y:true,number:true,required:false,defaultValue:0})}AR.datapoints.format=Ae}if(AR.datapoints.pointsize!=null){continue}if(AR.datapoints.pointsize==null){AR.datapoints.pointsize=Ae.length}AX=AR.datapoints.pointsize;Ab=AR.datapoints.points;insertSteps=AR.lines.show&&AR.lines.steps;AR.xaxis.used=AR.yaxis.used=true;for(Aa=AZ=0;Aa<Ah.length;++Aa,AZ+=AX){AT=Ah[Aa];var AM=AT==null;if(!AM){for(AV=0;AV<AX;++AV){Ai=AT[AV];Af=Ae[AV];if(Af){if(Af.number&&Ai!=null){Ai=+Ai;if(isNaN(Ai)){Ai=null}}if(Ai==null){if(Af.required){AM=true}if(Af.defaultValue!=null){Ai=Af.defaultValue}}}Ab[AZ+AV]=Ai}}if(AM){for(AV=0;AV<AX;++AV){Ai=Ab[AZ+AV];if(Ai!=null){Af=Ae[AV];if(Af.x){AN(AR.xaxis,Ai,Ai)}if(Af.y){AN(AR.yaxis,Ai,Ai)}}Ab[AZ+AV]=null}}else{if(insertSteps&&AZ>0&&Ab[AZ-AX]!=null&&Ab[AZ-AX]!=Ab[AZ]&&Ab[AZ-AX+1]!=Ab[AZ+1]){for(AV=0;AV<AX;++AV){Ab[AZ+AX+AV]=Ab[AZ+AV]}Ab[AZ+1]=Ab[AZ-AX+1];AZ+=AX}}}}for(Ac=0;Ac<O.length;++Ac){AR=O[Ac];Z(L.processDatapoints,[AR,AR.datapoints])}for(Ac=0;Ac<O.length;++Ac){AR=O[Ac];Ab=AR.datapoints.points,AX=AR.datapoints.pointsize;var AS=AW,AY=AW,AU=AQ,Ad=AQ;for(Aa=0;Aa<Ab.length;Aa+=AX){if(Ab[Aa]==null){continue}for(AV=0;AV<AX;++AV){Ai=Ab[Aa+AV];Af=Ae[AV];if(!Af){continue}if(Af.x){if(Ai<AS){AS=Ai}if(Ai>AU){AU=Ai}}if(Af.y){if(Ai<AY){AY=Ai}if(Ai>Ad){Ad=Ai}}}}if(AR.bars.show){var Ag=AR.bars.align=="left"?0:-AR.bars.barWidth/2;if(AR.bars.horizontal){AY+=Ag;Ad+=Ag+AR.bars.barWidth}else{AS+=Ag;AU+=Ag+AR.bars.barWidth}}AN(AR.xaxis,AS,AU);AN(AR.yaxis,AY,Ad)}for(AK in s){if(s[AK].datamin==AW){s[AK].datamin=null}if(s[AK].datamax==AQ){s[AK].datamax=null}}}function c(){function AK(AM,AL){var AN=document.createElement("canvas");AN.width=AM;AN.height=AL;if(C.browser.msie){AN=window.G_vmlCanvasManager.initElement(AN)}return AN}y=l.width();Q=l.height();l.html("");if(l.css("position")=="static"){l.css("position","relative")}if(y<=0||Q<=0){throw"Invalid dimensions for plot, width = "+y+", height = "+Q}if(C.browser.msie){window.G_vmlCanvasManager.init_(document)}P=C(AK(y,Q)).appendTo(l).get(0);Y=P.getContext("2d");AC=C(AK(y,Q)).css({position:"absolute",left:0,top:0}).appendTo(l).get(0);AJ=AC.getContext("2d");AJ.stroke()}function AG(){AD=C([AC,P]);if(g.grid.hoverable){AD.mousemove(D)}if(g.grid.clickable){AD.click(d)}Z(L.bindEvents,[AD])}function k(){function AL(AT,AU){function AP(AV){return AV}var AS,AO,AQ=AU.transform||AP,AR=AU.inverseTransform;if(AT==s.xaxis||AT==s.x2axis){AS=AT.scale=I/(AQ(AT.max)-AQ(AT.min));AO=AQ(AT.min);if(AQ==AP){AT.p2c=function(AV){return(AV-AO)*AS}}else{AT.p2c=function(AV){return(AQ(AV)-AO)*AS}}if(!AR){AT.c2p=function(AV){return AO+AV/AS}}else{AT.c2p=function(AV){return AR(AO+AV/AS)}}}else{AS=AT.scale=t/(AQ(AT.max)-AQ(AT.min));AO=AQ(AT.max);if(AQ==AP){AT.p2c=function(AV){return(AO-AV)*AS}}else{AT.p2c=function(AV){return(AO-AQ(AV))*AS}}if(!AR){AT.c2p=function(AV){return AO-AV/AS}}else{AT.c2p=function(AV){return AR(AO-AV/AS)}}}}function AN(AR,AT){var AQ,AS=[],AP;AR.labelWidth=AT.labelWidth;AR.labelHeight=AT.labelHeight;if(AR==s.xaxis||AR==s.x2axis){if(AR.labelWidth==null){AR.labelWidth=y/(AR.ticks.length>0?AR.ticks.length:1)}if(AR.labelHeight==null){AS=[];for(AQ=0;AQ<AR.ticks.length;++AQ){AP=AR.ticks[AQ].label;if(AP){AS.push('<div class="tickLabel" style="float:left;width:'+AR.labelWidth+'px">'+AP+"</div>")}}if(AS.length>0){var AO=C('<div style="position:absolute;top:-10000px;width:10000px;font-size:smaller">'+AS.join("")+'<div style="clear:left"></div></div>').appendTo(l);AR.labelHeight=AO.height();AO.remove()}}}else{if(AR.labelWidth==null||AR.labelHeight==null){for(AQ=0;AQ<AR.ticks.length;++AQ){AP=AR.ticks[AQ].label;if(AP){AS.push('<div class="tickLabel">'+AP+"</div>")}}if(AS.length>0){var AO=C('<div style="position:absolute;top:-10000px;font-size:smaller">'+AS.join("")+"</div>").appendTo(l);if(AR.labelWidth==null){AR.labelWidth=AO.width()}if(AR.labelHeight==null){AR.labelHeight=AO.find("div").height()}AO.remove()}}}if(AR.labelWidth==null){AR.labelWidth=0}if(AR.labelHeight==null){AR.labelHeight=0}}function AM(){var AP=g.grid.borderWidth;for(i=0;i<O.length;++i){AP=Math.max(AP,2*(O[i].points.radius+O[i].points.lineWidth/2))}e.left=e.right=e.top=e.bottom=AP;var AO=g.grid.labelMargin+g.grid.borderWidth;if(s.xaxis.labelHeight>0){e.bottom=Math.max(AP,s.xaxis.labelHeight+AO)}if(s.yaxis.labelWidth>0){e.left=Math.max(AP,s.yaxis.labelWidth+AO)}if(s.x2axis.labelHeight>0){e.top=Math.max(AP,s.x2axis.labelHeight+AO)}if(s.y2axis.labelWidth>0){e.right=Math.max(AP,s.y2axis.labelWidth+AO)}I=y-e.left-e.right;t=Q-e.bottom-e.top}var AK;for(AK in s){K(s[AK],g[AK])}if(g.grid.show){for(AK in s){F(s[AK],g[AK]);p(s[AK],g[AK]);AN(s[AK],g[AK])}AM()}else{e.left=e.right=e.top=e.bottom=0;I=y;t=Q}for(AK in s){AL(s[AK],g[AK])}if(g.grid.show){h()}AI()}function K(AN,AQ){var AM=+(AQ.min!=null?AQ.min:AN.datamin),AK=+(AQ.max!=null?AQ.max:AN.datamax),AP=AK-AM;if(AP==0){var AL=AK==0?1:0.01;if(AQ.min==null){AM-=AL}if(AQ.max==null||AQ.min!=null){AK+=AL}}else{var AO=AQ.autoscaleMargin;if(AO!=null){if(AQ.min==null){AM-=AP*AO;if(AM<0&&AN.datamin!=null&&AN.datamin>=0){AM=0}}if(AQ.max==null){AK+=AP*AO;if(AK>0&&AN.datamax!=null&&AN.datamax<=0){AK=0}}}}AN.min=AM;AN.max=AK}function F(AP,AS){var AO;if(typeof AS.ticks=="number"&&AS.ticks>0){AO=AS.ticks}else{if(AP==s.xaxis||AP==s.x2axis){AO=0.3*Math.sqrt(y)}else{AO=0.3*Math.sqrt(Q)}}var AX=(AP.max-AP.min)/AO,AZ,AT,AV,AW,AR,AM,AL;if(AS.mode=="time"){var AU={second:1000,minute:60*1000,hour:60*60*1000,day:24*60*60*1000,month:30*24*60*60*1000,year:365.2425*24*60*60*1000};var AY=[[1,"second"],[2,"second"],[5,"second"],[10,"second"],[30,"second"],[1,"minute"],[2,"minute"],[5,"minute"],[10,"minute"],[30,"minute"],[1,"hour"],[2,"hour"],[4,"hour"],[8,"hour"],[12,"hour"],[1,"day"],[2,"day"],[3,"day"],[0.25,"month"],[0.5,"month"],[1,"month"],[2,"month"],[3,"month"],[6,"month"],[1,"year"]];var AN=0;if(AS.minTickSize!=null){if(typeof AS.tickSize=="number"){AN=AS.tickSize}else{AN=AS.minTickSize[0]*AU[AS.minTickSize[1]]}}for(AR=0;AR<AY.length-1;++AR){if(AX<(AY[AR][0]*AU[AY[AR][1]]+AY[AR+1][0]*AU[AY[AR+1][1]])/2&&AY[AR][0]*AU[AY[AR][1]]>=AN){break}}AZ=AY[AR][0];AV=AY[AR][1];if(AV=="year"){AM=Math.pow(10,Math.floor(Math.log(AX/AU.year)/Math.LN10));AL=(AX/AU.year)/AM;if(AL<1.5){AZ=1}else{if(AL<3){AZ=2}else{if(AL<7.5){AZ=5}else{AZ=10}}}AZ*=AM}if(AS.tickSize){AZ=AS.tickSize[0];AV=AS.tickSize[1]}AT=function(Ac){var Ah=[],Af=Ac.tickSize[0],Ai=Ac.tickSize[1],Ag=new Date(Ac.min);var Ab=Af*AU[Ai];if(Ai=="second"){Ag.setUTCSeconds(A(Ag.getUTCSeconds(),Af))}if(Ai=="minute"){Ag.setUTCMinutes(A(Ag.getUTCMinutes(),Af))}if(Ai=="hour"){Ag.setUTCHours(A(Ag.getUTCHours(),Af))}if(Ai=="month"){Ag.setUTCMonth(A(Ag.getUTCMonth(),Af))}if(Ai=="year"){Ag.setUTCFullYear(A(Ag.getUTCFullYear(),Af))}Ag.setUTCMilliseconds(0);if(Ab>=AU.minute){Ag.setUTCSeconds(0)}if(Ab>=AU.hour){Ag.setUTCMinutes(0)}if(Ab>=AU.day){Ag.setUTCHours(0)}if(Ab>=AU.day*4){Ag.setUTCDate(1)}if(Ab>=AU.year){Ag.setUTCMonth(0)}var Ak=0,Aj=Number.NaN,Ad;do{Ad=Aj;Aj=Ag.getTime();Ah.push({v:Aj,label:Ac.tickFormatter(Aj,Ac)});if(Ai=="month"){if(Af<1){Ag.setUTCDate(1);var Aa=Ag.getTime();Ag.setUTCMonth(Ag.getUTCMonth()+1);var Ae=Ag.getTime();Ag.setTime(Aj+Ak*AU.hour+(Ae-Aa)*Af);Ak=Ag.getUTCHours();Ag.setUTCHours(0)}else{Ag.setUTCMonth(Ag.getUTCMonth()+Af)}}else{if(Ai=="year"){Ag.setUTCFullYear(Ag.getUTCFullYear()+Af)}else{Ag.setTime(Aj+Ab)}}}while(Aj<Ac.max&&Aj!=Ad);return Ah};AW=function(Aa,Ad){var Af=new Date(Aa);if(AS.timeformat!=null){return C.plot.formatDate(Af,AS.timeformat,AS.monthNames)}var Ab=Ad.tickSize[0]*AU[Ad.tickSize[1]];var Ac=Ad.max-Ad.min;var Ae=(AS.twelveHourClock)?" %p":"";if(Ab<AU.minute){fmt="%h:%M:%S"+Ae}else{if(Ab<AU.day){if(Ac<2*AU.day){fmt="%h:%M"+Ae}else{fmt="%b %d %h:%M"+Ae}}else{if(Ab<AU.month){fmt="%b %d"}else{if(Ab<AU.year){if(Ac<AU.year){fmt="%b"}else{fmt="%b %y"}}else{fmt="%y"}}}}return C.plot.formatDate(Af,fmt,AS.monthNames)}}else{var AK=AS.tickDecimals;var AQ=-Math.floor(Math.log(AX)/Math.LN10);if(AK!=null&&AQ>AK){AQ=AK}AM=Math.pow(10,-AQ);AL=AX/AM;if(AL<1.5){AZ=1}else{if(AL<3){AZ=2;if(AL>2.25&&(AK==null||AQ+1<=AK)){AZ=2.5;++AQ}}else{if(AL<7.5){AZ=5}else{AZ=10}}}AZ*=AM;if(AS.minTickSize!=null&&AZ<AS.minTickSize){AZ=AS.minTickSize}if(AS.tickSize!=null){AZ=AS.tickSize}AP.tickDecimals=Math.max(0,(AK!=null)?AK:AQ);AT=function(Ac){var Ae=[];var Af=A(Ac.min,Ac.tickSize),Ab=0,Aa=Number.NaN,Ad;do{Ad=Aa;Aa=Af+Ab*Ac.tickSize;Ae.push({v:Aa,label:Ac.tickFormatter(Aa,Ac)});++Ab}while(Aa<Ac.max&&Aa!=Ad);return Ae};AW=function(Aa,Ab){return Aa.toFixed(Ab.tickDecimals)}}AP.tickSize=AV?[AZ,AV]:AZ;AP.tickGenerator=AT;if(C.isFunction(AS.tickFormatter)){AP.tickFormatter=function(Aa,Ab){return""+AS.tickFormatter(Aa,Ab)}}else{AP.tickFormatter=AW}}function p(AO,AQ){AO.ticks=[];if(!AO.used){return }if(AQ.ticks==null){AO.ticks=AO.tickGenerator(AO)}else{if(typeof AQ.ticks=="number"){if(AQ.ticks>0){AO.ticks=AO.tickGenerator(AO)}}else{if(AQ.ticks){var AP=AQ.ticks;if(C.isFunction(AP)){AP=AP({min:AO.min,max:AO.max})}var AN,AK;for(AN=0;AN<AP.length;++AN){var AL=null;var AM=AP[AN];if(typeof AM=="object"){AK=AM[0];if(AM.length>1){AL=AM[1]}}else{AK=AM}if(AL==null){AL=AO.tickFormatter(AK,AO)}AO.ticks[AN]={v:AK,label:AL}}}}}if(AQ.autoscaleMargin!=null&&AO.ticks.length>0){if(AQ.min==null){AO.min=Math.min(AO.min,AO.ticks[0].v)}if(AQ.max==null&&AO.ticks.length>1){AO.max=Math.max(AO.max,AO.ticks[AO.ticks.length-1].v)}}}function AH(){Y.clearRect(0,0,y,Q);var AL=g.grid;if(AL.show&&!AL.aboveData){S()}for(var AK=0;AK<O.length;++AK){AA(O[AK])}Z(L.draw,[Y]);if(AL.show&&AL.aboveData){S()}}function N(AL,AR){var AO=AR+"axis",AK=AR+"2axis",AN,AQ,AP,AM;if(AL[AO]){AN=s[AO];AQ=AL[AO].from;AP=AL[AO].to}else{if(AL[AK]){AN=s[AK];AQ=AL[AK].from;AP=AL[AK].to}else{AN=s[AO];AQ=AL[AR+"1"];AP=AL[AR+"2"]}}if(AQ!=null&&AP!=null&&AQ>AP){return{from:AP,to:AQ,axis:AN}}return{from:AQ,to:AP,axis:AN}}function S(){var AO;Y.save();Y.translate(e.left,e.top);if(g.grid.backgroundColor){Y.fillStyle=R(g.grid.backgroundColor,t,0,"rgba(255, 255, 255, 0)");Y.fillRect(0,0,I,t)}var AL=g.grid.markings;if(AL){if(C.isFunction(AL)){AL=AL({xmin:s.xaxis.min,xmax:s.xaxis.max,ymin:s.yaxis.min,ymax:s.yaxis.max,xaxis:s.xaxis,yaxis:s.yaxis,x2axis:s.x2axis,y2axis:s.y2axis})}for(AO=0;AO<AL.length;++AO){var AK=AL[AO],AQ=N(AK,"x"),AN=N(AK,"y");if(AQ.from==null){AQ.from=AQ.axis.min}if(AQ.to==null){AQ.to=AQ.axis.max}if(AN.from==null){AN.from=AN.axis.min}if(AN.to==null){AN.to=AN.axis.max}if(AQ.to<AQ.axis.min||AQ.from>AQ.axis.max||AN.to<AN.axis.min||AN.from>AN.axis.max){continue}AQ.from=Math.max(AQ.from,AQ.axis.min);AQ.to=Math.min(AQ.to,AQ.axis.max);AN.from=Math.max(AN.from,AN.axis.min);AN.to=Math.min(AN.to,AN.axis.max);if(AQ.from==AQ.to&&AN.from==AN.to){continue}AQ.from=AQ.axis.p2c(AQ.from);AQ.to=AQ.axis.p2c(AQ.to);AN.from=AN.axis.p2c(AN.from);AN.to=AN.axis.p2c(AN.to);if(AQ.from==AQ.to||AN.from==AN.to){Y.beginPath();Y.strokeStyle=AK.color||g.grid.markingsColor;Y.lineWidth=AK.lineWidth||g.grid.markingsLineWidth;Y.moveTo(AQ.from,AN.from);Y.lineTo(AQ.to,AN.to);Y.stroke()}else{Y.fillStyle=AK.color||g.grid.markingsColor;Y.fillRect(AQ.from,AN.to,AQ.to-AQ.from,AN.from-AN.to)}}}Y.lineWidth=1;Y.strokeStyle=g.grid.tickColor;Y.beginPath();var AM,AP=s.xaxis;for(AO=0;AO<AP.ticks.length;++AO){AM=AP.ticks[AO].v;if(AM<=AP.min||AM>=s.xaxis.max){continue}Y.moveTo(Math.floor(AP.p2c(AM))+Y.lineWidth/2,0);Y.lineTo(Math.floor(AP.p2c(AM))+Y.lineWidth/2,t)}AP=s.yaxis;for(AO=0;AO<AP.ticks.length;++AO){AM=AP.ticks[AO].v;if(AM<=AP.min||AM>=AP.max){continue}Y.moveTo(0,Math.floor(AP.p2c(AM))+Y.lineWidth/2);Y.lineTo(I,Math.floor(AP.p2c(AM))+Y.lineWidth/2)}AP=s.x2axis;for(AO=0;AO<AP.ticks.length;++AO){AM=AP.ticks[AO].v;if(AM<=AP.min||AM>=AP.max){continue}Y.moveTo(Math.floor(AP.p2c(AM))+Y.lineWidth/2,-5);Y.lineTo(Math.floor(AP.p2c(AM))+Y.lineWidth/2,5)}AP=s.y2axis;for(AO=0;AO<AP.ticks.length;++AO){AM=AP.ticks[AO].v;if(AM<=AP.min||AM>=AP.max){continue}Y.moveTo(I-5,Math.floor(AP.p2c(AM))+Y.lineWidth/2);Y.lineTo(I+5,Math.floor(AP.p2c(AM))+Y.lineWidth/2)}Y.stroke();if(g.grid.borderWidth){var AR=g.grid.borderWidth;Y.lineWidth=AR;Y.strokeStyle=g.grid.borderColor;Y.strokeRect(-AR/2,-AR/2,I+AR,t+AR)}Y.restore()}function h(){l.find(".tickLabels").remove();var AK=['<div class="tickLabels" style="font-size:smaller;color:'+g.grid.color+'">'];function AM(AP,AQ){for(var AO=0;AO<AP.ticks.length;++AO){var AN=AP.ticks[AO];if(!AN.label||AN.v<AP.min||AN.v>AP.max){continue}AK.push(AQ(AN,AP))}}var AL=g.grid.labelMargin+g.grid.borderWidth;AM(s.xaxis,function(AN,AO){return'<div style="position:absolute;top:'+(e.top+t+AL)+"px;left:"+Math.round(e.left+AO.p2c(AN.v)-AO.labelWidth/2)+"px;width:"+AO.labelWidth+'px;text-align:center" class="tickLabel">'+AN.label+"</div>"});AM(s.yaxis,function(AN,AO){return'<div style="position:absolute;top:'+Math.round(e.top+AO.p2c(AN.v)-AO.labelHeight/2)+"px;right:"+(e.right+I+AL)+"px;width:"+AO.labelWidth+'px;text-align:right" class="tickLabel">'+AN.label+"</div>"});AM(s.x2axis,function(AN,AO){return'<div style="position:absolute;bottom:'+(e.bottom+t+AL)+"px;left:"+Math.round(e.left+AO.p2c(AN.v)-AO.labelWidth/2)+"px;width:"+AO.labelWidth+'px;text-align:center" class="tickLabel">'+AN.label+"</div>"});AM(s.y2axis,function(AN,AO){return'<div style="position:absolute;top:'+Math.round(e.top+AO.p2c(AN.v)-AO.labelHeight/2)+"px;left:"+(e.left+I+AL)+"px;width:"+AO.labelWidth+'px;text-align:left" class="tickLabel">'+AN.label+"</div>"});AK.push("</div>");l.append(AK.join(""))}function AA(AK){if(AK.lines.show){a(AK)}if(AK.bars.show){n(AK)}if(AK.points.show){o(AK)}}function a(AN){function AM(AY,AZ,AR,Ad,Ac){var Ae=AY.points,AS=AY.pointsize,AW=null,AV=null;Y.beginPath();for(var AX=AS;AX<Ae.length;AX+=AS){var AU=Ae[AX-AS],Ab=Ae[AX-AS+1],AT=Ae[AX],Aa=Ae[AX+1];if(AU==null||AT==null){continue}if(Ab<=Aa&&Ab<Ac.min){if(Aa<Ac.min){continue}AU=(Ac.min-Ab)/(Aa-Ab)*(AT-AU)+AU;Ab=Ac.min}else{if(Aa<=Ab&&Aa<Ac.min){if(Ab<Ac.min){continue}AT=(Ac.min-Ab)/(Aa-Ab)*(AT-AU)+AU;Aa=Ac.min}}if(Ab>=Aa&&Ab>Ac.max){if(Aa>Ac.max){continue}AU=(Ac.max-Ab)/(Aa-Ab)*(AT-AU)+AU;Ab=Ac.max}else{if(Aa>=Ab&&Aa>Ac.max){if(Ab>Ac.max){continue}AT=(Ac.max-Ab)/(Aa-Ab)*(AT-AU)+AU;Aa=Ac.max}}if(AU<=AT&&AU<Ad.min){if(AT<Ad.min){continue}Ab=(Ad.min-AU)/(AT-AU)*(Aa-Ab)+Ab;AU=Ad.min}else{if(AT<=AU&&AT<Ad.min){if(AU<Ad.min){continue}Aa=(Ad.min-AU)/(AT-AU)*(Aa-Ab)+Ab;AT=Ad.min}}if(AU>=AT&&AU>Ad.max){if(AT>Ad.max){continue}Ab=(Ad.max-AU)/(AT-AU)*(Aa-Ab)+Ab;AU=Ad.max}else{if(AT>=AU&&AT>Ad.max){if(AU>Ad.max){continue}Aa=(Ad.max-AU)/(AT-AU)*(Aa-Ab)+Ab;AT=Ad.max}}if(AU!=AW||Ab!=AV){Y.moveTo(Ad.p2c(AU)+AZ,Ac.p2c(Ab)+AR)}AW=AT;AV=Aa;Y.lineTo(Ad.p2c(AT)+AZ,Ac.p2c(Aa)+AR)}Y.stroke()}function AO(AX,Ae,Ac){var Af=AX.points,AR=AX.pointsize,AS=Math.min(Math.max(0,Ac.min),Ac.max),Aa,AV=0,Ad=false;for(var AW=AR;AW<Af.length;AW+=AR){var AU=Af[AW-AR],Ab=Af[AW-AR+1],AT=Af[AW],AZ=Af[AW+1];if(Ad&&AU!=null&&AT==null){Y.lineTo(Ae.p2c(AV),Ac.p2c(AS));Y.fill();Ad=false;continue}if(AU==null||AT==null){continue}if(AU<=AT&&AU<Ae.min){if(AT<Ae.min){continue}Ab=(Ae.min-AU)/(AT-AU)*(AZ-Ab)+Ab;AU=Ae.min}else{if(AT<=AU&&AT<Ae.min){if(AU<Ae.min){continue}AZ=(Ae.min-AU)/(AT-AU)*(AZ-Ab)+Ab;AT=Ae.min}}if(AU>=AT&&AU>Ae.max){if(AT>Ae.max){continue}Ab=(Ae.max-AU)/(AT-AU)*(AZ-Ab)+Ab;AU=Ae.max}else{if(AT>=AU&&AT>Ae.max){if(AU>Ae.max){continue}AZ=(Ae.max-AU)/(AT-AU)*(AZ-Ab)+Ab;AT=Ae.max}}if(!Ad){Y.beginPath();Y.moveTo(Ae.p2c(AU),Ac.p2c(AS));Ad=true}if(Ab>=Ac.max&&AZ>=Ac.max){Y.lineTo(Ae.p2c(AU),Ac.p2c(Ac.max));Y.lineTo(Ae.p2c(AT),Ac.p2c(Ac.max));AV=AT;continue}else{if(Ab<=Ac.min&&AZ<=Ac.min){Y.lineTo(Ae.p2c(AU),Ac.p2c(Ac.min));Y.lineTo(Ae.p2c(AT),Ac.p2c(Ac.min));AV=AT;continue}}var Ag=AU,AY=AT;if(Ab<=AZ&&Ab<Ac.min&&AZ>=Ac.min){AU=(Ac.min-Ab)/(AZ-Ab)*(AT-AU)+AU;Ab=Ac.min}else{if(AZ<=Ab&&AZ<Ac.min&&Ab>=Ac.min){AT=(Ac.min-Ab)/(AZ-Ab)*(AT-AU)+AU;AZ=Ac.min}}if(Ab>=AZ&&Ab>Ac.max&&AZ<=Ac.max){AU=(Ac.max-Ab)/(AZ-Ab)*(AT-AU)+AU;Ab=Ac.max}else{if(AZ>=Ab&&AZ>Ac.max&&Ab<=Ac.max){AT=(Ac.max-Ab)/(AZ-Ab)*(AT-AU)+AU;AZ=Ac.max}}if(AU!=Ag){if(Ab<=Ac.min){Aa=Ac.min}else{Aa=Ac.max}Y.lineTo(Ae.p2c(Ag),Ac.p2c(Aa));Y.lineTo(Ae.p2c(AU),Ac.p2c(Aa))}Y.lineTo(Ae.p2c(AU),Ac.p2c(Ab));Y.lineTo(Ae.p2c(AT),Ac.p2c(AZ));if(AT!=AY){if(AZ<=Ac.min){Aa=Ac.min}else{Aa=Ac.max}Y.lineTo(Ae.p2c(AT),Ac.p2c(Aa));Y.lineTo(Ae.p2c(AY),Ac.p2c(Aa))}AV=Math.max(AT,AY)}if(Ad){Y.lineTo(Ae.p2c(AV),Ac.p2c(AS));Y.fill()}}Y.save();Y.translate(e.left,e.top);Y.lineJoin="round";var AP=AN.lines.lineWidth,AK=AN.shadowSize;if(AP>0&&AK>0){Y.lineWidth=AK;Y.strokeStyle="rgba(0,0,0,0.1)";var AQ=Math.PI/18;AM(AN.datapoints,Math.sin(AQ)*(AP/2+AK/2),Math.cos(AQ)*(AP/2+AK/2),AN.xaxis,AN.yaxis);Y.lineWidth=AK/2;AM(AN.datapoints,Math.sin(AQ)*(AP/2+AK/4),Math.cos(AQ)*(AP/2+AK/4),AN.xaxis,AN.yaxis)}Y.lineWidth=AP;Y.strokeStyle=AN.color;var AL=V(AN.lines,AN.color,0,t);if(AL){Y.fillStyle=AL;AO(AN.datapoints,AN.xaxis,AN.yaxis)}if(AP>0){AM(AN.datapoints,0,0,AN.xaxis,AN.yaxis)}Y.restore()}function o(AN){function AP(AU,AT,Ab,AR,AV,AZ,AY){var Aa=AU.points,AQ=AU.pointsize;for(var AS=0;AS<Aa.length;AS+=AQ){var AX=Aa[AS],AW=Aa[AS+1];if(AX==null||AX<AZ.min||AX>AZ.max||AW<AY.min||AW>AY.max){continue}Y.beginPath();Y.arc(AZ.p2c(AX),AY.p2c(AW)+AR,AT,0,AV,false);if(Ab){Y.fillStyle=Ab;Y.fill()}Y.stroke()}}Y.save();Y.translate(e.left,e.top);var AO=AN.lines.lineWidth,AL=AN.shadowSize,AK=AN.points.radius;if(AO>0&&AL>0){var AM=AL/2;Y.lineWidth=AM;Y.strokeStyle="rgba(0,0,0,0.1)";AP(AN.datapoints,AK,null,AM+AM/2,Math.PI,AN.xaxis,AN.yaxis);Y.strokeStyle="rgba(0,0,0,0.2)";AP(AN.datapoints,AK,null,AM/2,Math.PI,AN.xaxis,AN.yaxis)}Y.lineWidth=AO;Y.strokeStyle=AN.color;AP(AN.datapoints,AK,V(AN.points,AN.color),0,2*Math.PI,AN.xaxis,AN.yaxis);Y.restore()}function AB(AV,AU,Ad,AQ,AY,AN,AL,AT,AS,Ac,AZ){var AM,Ab,AR,AX,AO,AK,AW,AP,Aa;if(AZ){AP=AK=AW=true;AO=false;AM=Ad;Ab=AV;AX=AU+AQ;AR=AU+AY;if(Ab<AM){Aa=Ab;Ab=AM;AM=Aa;AO=true;AK=false}}else{AO=AK=AW=true;AP=false;AM=AV+AQ;Ab=AV+AY;AR=Ad;AX=AU;if(AX<AR){Aa=AX;AX=AR;AR=Aa;AP=true;AW=false}}if(Ab<AT.min||AM>AT.max||AX<AS.min||AR>AS.max){return }if(AM<AT.min){AM=AT.min;AO=false}if(Ab>AT.max){Ab=AT.max;AK=false}if(AR<AS.min){AR=AS.min;AP=false}if(AX>AS.max){AX=AS.max;AW=false}AM=AT.p2c(AM);AR=AS.p2c(AR);Ab=AT.p2c(Ab);AX=AS.p2c(AX);if(AL){Ac.beginPath();Ac.moveTo(AM,AR);Ac.lineTo(AM,AX);Ac.lineTo(Ab,AX);Ac.lineTo(Ab,AR);Ac.fillStyle=AL(AR,AX);Ac.fill()}if(AO||AK||AW||AP){Ac.beginPath();Ac.moveTo(AM,AR+AN);if(AO){Ac.lineTo(AM,AX+AN)}else{Ac.moveTo(AM,AX+AN)}if(AW){Ac.lineTo(Ab,AX+AN)}else{Ac.moveTo(Ab,AX+AN)}if(AK){Ac.lineTo(Ab,AR+AN)}else{Ac.moveTo(Ab,AR+AN)}if(AP){Ac.lineTo(AM,AR+AN)}else{Ac.moveTo(AM,AR+AN)}Ac.stroke()}}function n(AM){function AL(AS,AR,AU,AP,AT,AW,AV){var AX=AS.points,AO=AS.pointsize;for(var AQ=0;AQ<AX.length;AQ+=AO){if(AX[AQ]==null){continue}AB(AX[AQ],AX[AQ+1],AX[AQ+2],AR,AU,AP,AT,AW,AV,Y,AM.bars.horizontal)}}Y.save();Y.translate(e.left,e.top);Y.lineWidth=AM.bars.lineWidth;Y.strokeStyle=AM.color;var AK=AM.bars.align=="left"?0:-AM.bars.barWidth/2;var AN=AM.bars.fill?function(AO,AP){return V(AM.bars,AM.color,AO,AP)}:null;AL(AM.datapoints,AK,AK+AM.bars.barWidth,0,AN,AM.xaxis,AM.yaxis);Y.restore()}function V(AM,AK,AL,AO){var AN=AM.fill;if(!AN){return null}if(AM.fillColor){return R(AM.fillColor,AL,AO,AK)}var AP=C.color.parse(AK);AP.a=typeof AN=="number"?AN:0.4;AP.normalize();return AP.toString()}function AI(){l.find(".legend").remove();if(!g.legend.show){return }var AP=[],AN=false,AV=g.legend.labelFormatter,AU,AR;for(i=0;i<O.length;++i){AU=O[i];AR=AU.label;if(!AR){continue}if(i%g.legend.noColumns==0){if(AN){AP.push("</tr>")}AP.push("<tr>");AN=true}if(AV){AR=AV(AR,AU)}AP.push('<td class="legendColorBox"><div style="border:1px solid '+g.legend.labelBoxBorderColor+';padding:1px"><div style="width:4px;height:0;border:5px solid '+AU.color+';overflow:hidden"></div></div></td><td class="legendLabel">'+AR+"</td>")}if(AN){AP.push("</tr>")}if(AP.length==0){return }var AT='<table style="font-size:smaller;color:'+g.grid.color+'">'+AP.join("")+"</table>";if(g.legend.container!=null){C(g.legend.container).html(AT)}else{var AQ="",AL=g.legend.position,AM=g.legend.margin;if(AM[0]==null){AM=[AM,AM]}if(AL.charAt(0)=="n"){AQ+="top:"+(AM[1]+e.top)+"px;"}else{if(AL.charAt(0)=="s"){AQ+="bottom:"+(AM[1]+e.bottom)+"px;"}}if(AL.charAt(1)=="e"){AQ+="right:"+(AM[0]+e.right)+"px;"}else{if(AL.charAt(1)=="w"){AQ+="left:"+(AM[0]+e.left)+"px;"}}var AS=C('<div class="legend">'+AT.replace('style="','style="position:absolute;'+AQ+";")+"</div>").appendTo(l);if(g.legend.backgroundOpacity!=0){var AO=g.legend.backgroundColor;if(AO==null){AO=g.grid.backgroundColor;if(AO&&typeof AO=="string"){AO=C.color.parse(AO)}else{AO=C.color.extract(AS,"background-color")}AO.a=1;AO=AO.toString()}var AK=AS.children();C('<div style="position:absolute;width:'+AK.width()+"px;height:"+AK.height()+"px;"+AQ+"background-color:"+AO+';"> </div>').prependTo(AS).css("opacity",g.legend.backgroundOpacity)}}}var w=[],J=null;function AF(AR,AP,AM){var AX=g.grid.mouseActiveRadius,Aj=AX*AX+1,Ah=null,Aa=false,Af,Ad;for(Af=0;Af<O.length;++Af){if(!AM(O[Af])){continue}var AY=O[Af],AQ=AY.xaxis,AO=AY.yaxis,Ae=AY.datapoints.points,Ac=AY.datapoints.pointsize,AZ=AQ.c2p(AR),AW=AO.c2p(AP),AL=AX/AQ.scale,AK=AX/AO.scale;if(AY.lines.show||AY.points.show){for(Ad=0;Ad<Ae.length;Ad+=Ac){var AT=Ae[Ad],AS=Ae[Ad+1];if(AT==null){continue}if(AT-AZ>AL||AT-AZ<-AL||AS-AW>AK||AS-AW<-AK){continue}var AV=Math.abs(AQ.p2c(AT)-AR),AU=Math.abs(AO.p2c(AS)-AP),Ab=AV*AV+AU*AU;if(Ab<=Aj){Aj=Ab;Ah=[Af,Ad/Ac]}}}if(AY.bars.show&&!Ah){var AN=AY.bars.align=="left"?0:-AY.bars.barWidth/2,Ag=AN+AY.bars.barWidth;for(Ad=0;Ad<Ae.length;Ad+=Ac){var AT=Ae[Ad],AS=Ae[Ad+1],Ai=Ae[Ad+2];if(AT==null){continue}if(O[Af].bars.horizontal?(AZ<=Math.max(Ai,AT)&&AZ>=Math.min(Ai,AT)&&AW>=AS+AN&&AW<=AS+Ag):(AZ>=AT+AN&&AZ<=AT+Ag&&AW>=Math.min(Ai,AS)&&AW<=Math.max(Ai,AS))){Ah=[Af,Ad/Ac]}}}}if(Ah){Af=Ah[0];Ad=Ah[1];Ac=O[Af].datapoints.pointsize;return{datapoint:O[Af].datapoints.points.slice(Ad*Ac,(Ad+1)*Ac),dataIndex:Ad,series:O[Af],seriesIndex:Af}}return null}function D(AK){if(g.grid.hoverable){H("plothover",AK,function(AL){return AL.hoverable!=false})}}function d(AK){H("plotclick",AK,function(AL){return AL.clickable!=false})}function H(AL,AK,AM){var AN=AD.offset(),AS={pageX:AK.pageX,pageY:AK.pageY},AQ=AK.pageX-AN.left-e.left,AO=AK.pageY-AN.top-e.top;if(s.xaxis.used){AS.x=s.xaxis.c2p(AQ)}if(s.yaxis.used){AS.y=s.yaxis.c2p(AO)}if(s.x2axis.used){AS.x2=s.x2axis.c2p(AQ)}if(s.y2axis.used){AS.y2=s.y2axis.c2p(AO)}var AT=AF(AQ,AO,AM);if(AT){AT.pageX=parseInt(AT.series.xaxis.p2c(AT.datapoint[0])+AN.left+e.left);AT.pageY=parseInt(AT.series.yaxis.p2c(AT.datapoint[1])+AN.top+e.top)}if(g.grid.autoHighlight){for(var AP=0;AP<w.length;++AP){var AR=w[AP];if(AR.auto==AL&&!(AT&&AR.series==AT.series&&AR.point==AT.datapoint)){x(AR.series,AR.point)}}if(AT){AE(AT.series,AT.datapoint,AL)}}l.trigger(AL,[AS,AT])}function q(){if(!J){J=setTimeout(v,30)}}function v(){J=null;AJ.save();AJ.clearRect(0,0,y,Q);AJ.translate(e.left,e.top);var AL,AK;for(AL=0;AL<w.length;++AL){AK=w[AL];if(AK.series.bars.show){z(AK.series,AK.point)}else{u(AK.series,AK.point)}}AJ.restore();Z(L.drawOverlay,[AJ])}function AE(AM,AK,AN){if(typeof AM=="number"){AM=O[AM]}if(typeof AK=="number"){AK=AM.data[AK]}var AL=j(AM,AK);if(AL==-1){w.push({series:AM,point:AK,auto:AN});q()}else{if(!AN){w[AL].auto=false}}}function x(AM,AK){if(AM==null&&AK==null){w=[];q()}if(typeof AM=="number"){AM=O[AM]}if(typeof AK=="number"){AK=AM.data[AK]}var AL=j(AM,AK);if(AL!=-1){w.splice(AL,1);q()}}function j(AM,AN){for(var AK=0;AK<w.length;++AK){var AL=w[AK];if(AL.series==AM&&AL.point[0]==AN[0]&&AL.point[1]==AN[1]){return AK}}return -1}function u(AN,AM){var AL=AM[0],AR=AM[1],AQ=AN.xaxis,AP=AN.yaxis;if(AL<AQ.min||AL>AQ.max||AR<AP.min||AR>AP.max){return }var AO=AN.points.radius+AN.points.lineWidth/2;AJ.lineWidth=AO;AJ.strokeStyle=C.color.parse(AN.color).scale("a",0.5).toString();var AK=1.5*AO;AJ.beginPath();AJ.arc(AQ.p2c(AL),AP.p2c(AR),AK,0,2*Math.PI,false);AJ.stroke()}function z(AN,AK){AJ.lineWidth=AN.bars.lineWidth;AJ.strokeStyle=C.color.parse(AN.color).scale("a",0.5).toString();var AM=C.color.parse(AN.color).scale("a",0.5).toString();var AL=AN.bars.align=="left"?0:-AN.bars.barWidth/2;AB(AK[0],AK[1],AK[2]||0,AL,AL+AN.bars.barWidth,0,function(){return AM},AN.xaxis,AN.yaxis,AJ,AN.bars.horizontal)}function R(AM,AL,AQ,AO){if(typeof AM=="string"){return AM}else{var AP=Y.createLinearGradient(0,AQ,0,AL);for(var AN=0,AK=AM.colors.length;AN<AK;++AN){var AR=AM.colors[AN];if(typeof AR!="string"){AR=C.color.parse(AO).scale("rgb",AR.brightness);AR.a*=AR.opacity;AR=AR.toString()}AP.addColorStop(AN/(AK-1),AR)}return AP}}}C.plot=function(G,E,D){var F=new B(C(G),E,D,C.plot.plugins);return F};C.plot.plugins=[];C.plot.formatDate=function(H,E,G){var L=function(N){N=""+N;return N.length==1?"0"+N:N};var D=[];var M=false;var K=H.getUTCHours();var I=K<12;if(G==null){G=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]}if(E.search(/%p|%P/)!=-1){if(K>12){K=K-12}else{if(K==0){K=12}}}for(var F=0;F<E.length;++F){var J=E.charAt(F);if(M){switch(J){case"h":J=""+K;break;case"H":J=L(K);break;case"M":J=L(H.getUTCMinutes());break;case"S":J=L(H.getUTCSeconds());break;case"d":J=""+H.getUTCDate();break;case"m":J=""+(H.getUTCMonth()+1);break;case"y":J=""+H.getUTCFullYear();break;case"b":J=""+G[H.getUTCMonth()];break;case"p":J=(I)?("am"):("pm");break;case"P":J=(I)?("AM"):("PM");break}D.push(J);M=false}else{if(J=="%"){M=true}else{D.push(J)}}}return D.join("")};function A(E,D){return D*Math.floor(E/D)}})(jQuery);
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/jquery.form.js b/forum/modules/template_loader.py/forum/skins/default/media/js/jquery.form.js
new file mode 100644 (file)
index 0000000..443114f
--- /dev/null
@@ -0,0 +1,654 @@
+/*
+ * jQuery Form Plugin
+ * version: 2.33 (22-SEP-2009)
+ * @requires jQuery v1.2.6 or later
+ *
+ * Examples and documentation at: http://malsup.com/jquery/form/
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ */
+;(function($) {
+
+/*
+       Usage Note:
+       -----------
+       Do not use both ajaxSubmit and ajaxForm on the same form.  These
+       functions are intended to be exclusive.  Use ajaxSubmit if you want
+       to bind your own submit handler to the form.  For example,
+
+       $(document).ready(function() {
+               $('#myForm').bind('submit', function() {
+                       $(this).ajaxSubmit({
+                               target: '#output'
+                       });
+                       return false; // <-- important!
+               });
+       });
+
+       Use ajaxForm when you want the plugin to manage all the event binding
+       for you.  For example,
+
+       $(document).ready(function() {
+               $('#myForm').ajaxForm({
+                       target: '#output'
+               });
+       });
+
+       When using ajaxForm, the ajaxSubmit function will be invoked for you
+       at the appropriate time.
+*/
+
+/**
+ * ajaxSubmit() provides a mechanism for immediately submitting
+ * an HTML form using AJAX.
+ */
+$.fn.ajaxSubmit = function(options) {
+       // fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
+       if (!this.length) {
+               log('ajaxSubmit: skipping submit process - no element selected');
+               return this;
+       }
+
+       if (typeof options == 'function')
+               options = { success: options };
+
+       var url = $.trim(this.attr('action'));
+       if (url) {
+               // clean url (don't include hash vaue)
+               url = (url.match(/^([^#]+)/)||[])[1];
+       }
+       url = url || window.location.href || '';
+
+       options = $.extend({
+               url:  url,
+               type: this.attr('method') || 'GET'
+       }, options || {});
+
+       // hook for manipulating the form data before it is extracted;
+       // convenient for use with rich editors like tinyMCE or FCKEditor
+       var veto = {};
+       this.trigger('form-pre-serialize', [this, options, veto]);
+       if (veto.veto) {
+               log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
+               return this;
+       }
+
+       // provide opportunity to alter form data before it is serialized
+       if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
+               log('ajaxSubmit: submit aborted via beforeSerialize callback');
+               return this;
+       }
+
+       var a = this.formToArray(options.semantic);
+       if (options.data) {
+               options.extraData = options.data;
+               for (var n in options.data) {
+                 if(options.data[n] instanceof Array) {
+                       for (var k in options.data[n])
+                         a.push( { name: n, value: options.data[n][k] } );
+                 }
+                 else
+                        a.push( { name: n, value: options.data[n] } );
+               }
+       }
+
+       // give pre-submit callback an opportunity to abort the submit
+       if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
+               log('ajaxSubmit: submit aborted via beforeSubmit callback');
+               return this;
+       }
+
+       // fire vetoable 'validate' event
+       this.trigger('form-submit-validate', [a, this, options, veto]);
+       if (veto.veto) {
+               log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
+               return this;
+       }
+
+       var q = $.param(a);
+
+       if (options.type.toUpperCase() == 'GET') {
+               options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
+               options.data = null;  // data is null for 'get'
+       }
+       else
+               options.data = q; // data is the query string for 'post'
+
+       var $form = this, callbacks = [];
+       if (options.resetForm) callbacks.push(function() { $form.resetForm(); });
+       if (options.clearForm) callbacks.push(function() { $form.clearForm(); });
+
+       // perform a load on the target only if dataType is not provided
+       if (!options.dataType && options.target) {
+               var oldSuccess = options.success || function(){};
+               callbacks.push(function(data) {
+                       $(options.target).html(data).each(oldSuccess, arguments);
+               });
+       }
+       else if (options.success)
+               callbacks.push(options.success);
+
+       options.success = function(data, status) {
+               for (var i=0, max=callbacks.length; i < max; i++)
+                       callbacks[i].apply(options, [data, status, $form]);
+       };
+
+       // are there files to upload?
+       var files = $('input:file', this).fieldValue();
+       var found = false;
+       for (var j=0; j < files.length; j++)
+               if (files[j])
+                       found = true;
+
+       var multipart = false;
+//     var mp = 'multipart/form-data';
+//     multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
+
+       // options.iframe allows user to force iframe mode
+   if (options.iframe || found || multipart) {
+          // hack to fix Safari hang (thanks to Tim Molendijk for this)
+          // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
+          if (options.closeKeepAlive)
+                  $.get(options.closeKeepAlive, fileUpload);
+          else
+                  fileUpload();
+          }
+   else{
+          $.ajax(options);
+   }
+
+       // fire 'notify' event
+       this.trigger('form-submit-notify', [this, options]);
+       return this;
+
+
+       // private function for handling file uploads (hat tip to YAHOO!)
+       function fileUpload() {
+               var form = $form[0];
+
+               if ($(':input[name=submit]', form).length) {
+                       alert('Error: Form elements must not be named "submit".');
+                       return;
+               }
+
+               var opts = $.extend({}, $.ajaxSettings, options);
+               var s = $.extend(true, {}, $.extend(true, {}, $.ajaxSettings), opts);
+
+               var id = 'jqFormIO' + (new Date().getTime());
+               var $io = $('<iframe id="' + id + '" name="' + id + '" src="about:blank" />');
+               var io = $io[0];
+
+               $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
+
+               var xhr = { // mock object
+                       aborted: 0,
+                       responseText: null,
+                       responseXML: null,
+                       status: 0,
+                       statusText: 'n/a',
+                       getAllResponseHeaders: function() {},
+                       getResponseHeader: function() {},
+                       setRequestHeader: function() {},
+                       abort: function() {
+                               this.aborted = 1;
+                               $io.attr('src','about:blank'); // abort op in progress
+                       }
+               };
+
+               var g = opts.global;
+               // trigger ajax global events so that activity/block indicators work like normal
+               if (g && ! $.active++) $.event.trigger("ajaxStart");
+               if (g) $.event.trigger("ajaxSend", [xhr, opts]);
+
+               if (s.beforeSend && s.beforeSend(xhr, s) === false) {
+                       s.global && $.active--;
+                       return;
+               }
+               if (xhr.aborted)
+                       return;
+
+               var cbInvoked = 0;
+               var timedOut = 0;
+
+               // add submitting element to data if we know it
+               var sub = form.clk;
+               if (sub) {
+                       var n = sub.name;
+                       if (n && !sub.disabled) {
+                               options.extraData = options.extraData || {};
+                               options.extraData[n] = sub.value;
+                               if (sub.type == "image") {
+                                       options.extraData[name+'.x'] = form.clk_x;
+                                       options.extraData[name+'.y'] = form.clk_y;
+                               }
+                       }
+               }
+
+               // take a breath so that pending repaints get some cpu time before the upload starts
+               setTimeout(function() {
+                       // make sure form attrs are set
+                       var t = $form.attr('target'), a = $form.attr('action');
+
+                       // update form attrs in IE friendly way
+                       form.setAttribute('target',id);
+                       if (form.getAttribute('method') != 'POST')
+                               form.setAttribute('method', 'POST');
+                       if (form.getAttribute('action') != opts.url)
+                               form.setAttribute('action', opts.url);
+
+                       // ie borks in some cases when setting encoding
+                       if (! options.skipEncodingOverride) {
+                               $form.attr({
+                                       encoding: 'multipart/form-data',
+                                       enctype:  'multipart/form-data'
+                               });
+                       }
+
+                       // support timout
+                       if (opts.timeout)
+                               setTimeout(function() { timedOut = true; cb(); }, opts.timeout);
+
+                       // add "extra" data to form if provided in options
+                       var extraInputs = [];
+                       try {
+                               if (options.extraData)
+                                       for (var n in options.extraData)
+                                               extraInputs.push(
+                                                       $('<input type="hidden" name="'+n+'" value="'+options.extraData[n]+'" />')
+                                                               .appendTo(form)[0]);
+
+                               // add iframe to doc and submit the form
+                               $io.appendTo('body');
+                               io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);
+                               form.submit();
+                       }
+                       finally {
+                               // reset attrs and remove "extra" input elements
+                               form.setAttribute('action',a);
+                               t ? form.setAttribute('target', t) : $form.removeAttr('target');
+                               $(extraInputs).remove();
+                       }
+               }, 10);
+
+               var domCheckCount = 50;
+
+               function cb() {
+                       if (cbInvoked++) return;
+
+                       io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false);
+
+                       var ok = true;
+                       try {
+                               if (timedOut) throw 'timeout';
+                               // extract the server response from the iframe
+                               var data, doc;
+
+                               doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
+                               
+                               var isXml = opts.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
+                               log('isXml='+isXml);
+                               if (!isXml && (doc.body == null || doc.body.innerHTML == '')) {
+                                       if (--domCheckCount) {
+                                               // in some browsers (Opera) the iframe DOM is not always traversable when
+                                               // the onload callback fires, so we loop a bit to accommodate
+                                               cbInvoked = 0;
+                                               setTimeout(cb, 100);
+                                               return;
+                                       }
+                                       log('Could not access iframe DOM after 50 tries.');
+                                       return;
+                               }
+
+                               xhr.responseText = doc.body ? doc.body.innerHTML : null;
+                               xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
+                               xhr.getResponseHeader = function(header){
+                                       var headers = {'content-type': opts.dataType};
+                                       return headers[header];
+                               };
+
+                               if (opts.dataType == 'json' || opts.dataType == 'script') {
+                                       // see if user embedded response in textarea
+                                       var ta = doc.getElementsByTagName('textarea')[0];
+                                       if (ta)
+                                               xhr.responseText = ta.value;
+                                       else {
+                                               // account for browsers injecting pre around json response
+                                               var pre = doc.getElementsByTagName('pre')[0];
+                                               if (pre)
+                                                       xhr.responseText = pre.innerHTML;
+                                       }                         
+                               }
+                               else if (opts.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) {
+                                       xhr.responseXML = toXml(xhr.responseText);
+                               }
+                               data = $.httpData(xhr, opts.dataType);
+                       }
+                       catch(e){
+                               ok = false;
+                               $.handleError(opts, xhr, 'error', e);
+                       }
+
+                       // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
+                       if (ok) {
+                               opts.success(data, 'success');
+                               if (g) $.event.trigger("ajaxSuccess", [xhr, opts]);
+                       }
+                       if (g) $.event.trigger("ajaxComplete", [xhr, opts]);
+                       if (g && ! --$.active) $.event.trigger("ajaxStop");
+                       if (opts.complete) opts.complete(xhr, ok ? 'success' : 'error');
+
+                       // clean up
+                       setTimeout(function() {
+                               $io.remove();
+                               xhr.responseXML = null;
+                       }, 100);
+               };
+
+               function toXml(s, doc) {
+                       if (window.ActiveXObject) {
+                               doc = new ActiveXObject('Microsoft.XMLDOM');
+                               doc.async = 'false';
+                               doc.loadXML(s);
+                       }
+                       else
+                               doc = (new DOMParser()).parseFromString(s, 'text/xml');
+                       return (doc && doc.documentElement && doc.documentElement.tagName != 'parsererror') ? doc : null;
+               };
+       };
+};
+
+/**
+ * ajaxForm() provides a mechanism for fully automating form submission.
+ *
+ * The advantages of using this method instead of ajaxSubmit() are:
+ *
+ * 1: This method will include coordinates for <input type="image" /> elements (if the element
+ *     is used to submit the form).
+ * 2. This method will include the submit element's name/value data (for the element that was
+ *     used to submit the form).
+ * 3. This method binds the submit() method to the form for you.
+ *
+ * The options argument for ajaxForm works exactly as it does for ajaxSubmit.  ajaxForm merely
+ * passes the options argument along after properly binding events for submit elements and
+ * the form itself.
+ */
+$.fn.ajaxForm = function(options) {
+       return this.ajaxFormUnbind().bind('submit.form-plugin', function() {
+               $(this).ajaxSubmit(options);
+               return false;
+       }).bind('click.form-plugin', function(e) {
+               var $el = $(e.target);
+               if (!($el.is(":submit,input:image"))) {
+                       return;
+               }
+               var form = this;
+               form.clk = e.target;
+               if (e.target.type == 'image') {
+                       if (e.offsetX != undefined) {
+                               form.clk_x = e.offsetX;
+                               form.clk_y = e.offsetY;
+                       } else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin
+                               var offset = $el.offset();
+                               form.clk_x = e.pageX - offset.left;
+                               form.clk_y = e.pageY - offset.top;
+                       } else {
+                               form.clk_x = e.pageX - e.target.offsetLeft;
+                               form.clk_y = e.pageY - e.target.offsetTop;
+                       }
+               }
+               // clear form vars
+               setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 10);
+       });
+};
+
+// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
+$.fn.ajaxFormUnbind = function() {
+       return this.unbind('submit.form-plugin click.form-plugin');
+};
+
+/**
+ * formToArray() gathers form element data into an array of objects that can
+ * be passed to any of the following ajax functions: $.get, $.post, or load.
+ * Each object in the array has both a 'name' and 'value' property.  An example of
+ * an array for a simple login form might be:
+ *
+ * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
+ *
+ * It is this array that is passed to pre-submit callback functions provided to the
+ * ajaxSubmit() and ajaxForm() methods.
+ */
+$.fn.formToArray = function(semantic) {
+       var a = [];
+       if (this.length == 0) return a;
+
+       var form = this[0];
+       var els = semantic ? form.getElementsByTagName('*') : form.elements;
+       if (!els) return a;
+       for(var i=0, max=els.length; i < max; i++) {
+               var el = els[i];
+               var n = el.name;
+               if (!n) continue;
+
+               if (semantic && form.clk && el.type == "image") {
+                       // handle image inputs on the fly when semantic == true
+                       if(!el.disabled && form.clk == el) {
+                               a.push({name: n, value: $(el).val()});
+                               a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
+                       }
+                       continue;
+               }
+
+               var v = $.fieldValue(el, true);
+               if (v && v.constructor == Array) {
+                       for(var j=0, jmax=v.length; j < jmax; j++)
+                               a.push({name: n, value: v[j]});
+               }
+               else if (v !== null && typeof v != 'undefined')
+                       a.push({name: n, value: v});
+       }
+
+       if (!semantic && form.clk) {
+               // input type=='image' are not found in elements array! handle it here
+               var $input = $(form.clk), input = $input[0], n = input.name;
+               if (n && !input.disabled && input.type == 'image') {
+                       a.push({name: n, value: $input.val()});
+                       a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
+               }
+       }
+       return a;
+};
+
+/**
+ * Serializes form data into a 'submittable' string. This method will return a string
+ * in the format: name1=value1&amp;name2=value2
+ */
+$.fn.formSerialize = function(semantic) {
+       //hand off to jQuery.param for proper encoding
+       return $.param(this.formToArray(semantic));
+};
+
+/**
+ * Serializes all field elements in the jQuery object into a query string.
+ * This method will return a string in the format: name1=value1&amp;name2=value2
+ */
+$.fn.fieldSerialize = function(successful) {
+       var a = [];
+       this.each(function() {
+               var n = this.name;
+               if (!n) return;
+               var v = $.fieldValue(this, successful);
+               if (v && v.constructor == Array) {
+                       for (var i=0,max=v.length; i < max; i++)
+                               a.push({name: n, value: v[i]});
+               }
+               else if (v !== null && typeof v != 'undefined')
+                       a.push({name: this.name, value: v});
+       });
+       //hand off to jQuery.param for proper encoding
+       return $.param(a);
+};
+
+/**
+ * Returns the value(s) of the element in the matched set.  For example, consider the following form:
+ *
+ *  <form><fieldset>
+ *       <input name="A" type="text" />
+ *       <input name="A" type="text" />
+ *       <input name="B" type="checkbox" value="B1" />
+ *       <input name="B" type="checkbox" value="B2"/>
+ *       <input name="C" type="radio" value="C1" />
+ *       <input name="C" type="radio" value="C2" />
+ *  </fieldset></form>
+ *
+ *  var v = $(':text').fieldValue();
+ *  // if no values are entered into the text inputs
+ *  v == ['','']
+ *  // if values entered into the text inputs are 'foo' and 'bar'
+ *  v == ['foo','bar']
+ *
+ *  var v = $(':checkbox').fieldValue();
+ *  // if neither checkbox is checked
+ *  v === undefined
+ *  // if both checkboxes are checked
+ *  v == ['B1', 'B2']
+ *
+ *  var v = $(':radio').fieldValue();
+ *  // if neither radio is checked
+ *  v === undefined
+ *  // if first radio is checked
+ *  v == ['C1']
+ *
+ * The successful argument controls whether or not the field element must be 'successful'
+ * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
+ * The default value of the successful argument is true.  If this value is false the value(s)
+ * for each element is returned.
+ *
+ * Note: This method *always* returns an array.  If no valid value can be determined the
+ *        array will be empty, otherwise it will contain one or more values.
+ */
+$.fn.fieldValue = function(successful) {
+       for (var val=[], i=0, max=this.length; i < max; i++) {
+               var el = this[i];
+               var v = $.fieldValue(el, successful);
+               if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length))
+                       continue;
+               v.constructor == Array ? $.merge(val, v) : val.push(v);
+       }
+       return val;
+};
+
+/**
+ * Returns the value of the field element.
+ */
+$.fieldValue = function(el, successful) {
+       var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
+       if (typeof successful == 'undefined') successful = true;
+
+       if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
+               (t == 'checkbox' || t == 'radio') && !el.checked ||
+               (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
+               tag == 'select' && el.selectedIndex == -1))
+                       return null;
+
+       if (tag == 'select') {
+               var index = el.selectedIndex;
+               if (index < 0) return null;
+               var a = [], ops = el.options;
+               var one = (t == 'select-one');
+               var max = (one ? index+1 : ops.length);
+               for(var i=(one ? index : 0); i < max; i++) {
+                       var op = ops[i];
+                       if (op.selected) {
+                               var v = op.value;
+                               if (!v) // extra pain for IE...
+                                       v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
+                               if (one) return v;
+                               a.push(v);
+                       }
+               }
+               return a;
+       }
+       return el.value;
+};
+
+/**
+ * Clears the form data.  Takes the following actions on the form's input fields:
+ *  - input text fields will have their 'value' property set to the empty string
+ *  - select elements will have their 'selectedIndex' property set to -1
+ *  - checkbox and radio inputs will have their 'checked' property set to false
+ *  - inputs of type submit, button, reset, and hidden will *not* be effected
+ *  - button elements will *not* be effected
+ */
+$.fn.clearForm = function() {
+       return this.each(function() {
+               $('input,select,textarea', this).clearFields();
+       });
+};
+
+/**
+ * Clears the selected form elements.
+ */
+$.fn.clearFields = $.fn.clearInputs = function() {
+       return this.each(function() {
+               var t = this.type, tag = this.tagName.toLowerCase();
+               if (t == 'text' || t == 'password' || tag == 'textarea')
+                       this.value = '';
+               else if (t == 'checkbox' || t == 'radio')
+                       this.checked = false;
+               else if (tag == 'select')
+                       this.selectedIndex = -1;
+       });
+};
+
+/**
+ * Resets the form data.  Causes all form elements to be reset to their original value.
+ */
+$.fn.resetForm = function() {
+       return this.each(function() {
+               // guard against an input with the name of 'reset'
+               // note that IE reports the reset function as an 'object'
+               if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType))
+                       this.reset();
+       });
+};
+
+/**
+ * Enables or disables any matching elements.
+ */
+$.fn.enable = function(b) {
+       if (b == undefined) b = true;
+       return this.each(function() {
+               this.disabled = !b;
+       });
+};
+
+/**
+ * Checks/unchecks any matching checkboxes or radio buttons and
+ * selects/deselects and matching option elements.
+ */
+$.fn.selected = function(select) {
+       if (select == undefined) select = true;
+       return this.each(function() {
+               var t = this.type;
+               if (t == 'checkbox' || t == 'radio')
+                       this.checked = select;
+               else if (this.tagName.toLowerCase() == 'option') {
+                       var $sel = $(this).parent('select');
+                       if (select && $sel[0] && $sel[0].type == 'select-one') {
+                               // deselect all other options
+                               $sel.find('option').selected(false);
+                       }
+                       this.selected = select;
+               }
+       });
+};
+
+// helper fn for console logging
+// set $.fn.ajaxSubmit.debug to true to enable debug logging
+function log() {
+       if ($.fn.ajaxSubmit.debug && window.console && window.console.log)
+               window.console.log('[jquery.form] ' + Array.prototype.join.call(arguments,''));
+};
+
+})(jQuery);
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/jquery.i18n.js b/forum/modules/template_loader.py/forum/skins/default/media/js/jquery.i18n.js
new file mode 100644 (file)
index 0000000..0a155a3
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * jQuery i18n plugin
+ * @requires jQuery v1.1 or later
+ *
+ * Examples at: http://recurser.com/articles/2008/02/21/jquery-i18n-translation-plugin/
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ *
+ * Based on 'javascript i18n that almost doesn't suck' by markos
+ * http://markos.gaivo.net/blog/?p=100
+ *
+ * Revision: $Id$
+ * Version: 1.0.0  Feb-10-2008
+ */
+ (function($) {
+/**
+ * i18n provides a mechanism for translating strings using a jscript dictionary.
+ *
+ */
+
+
+/*
+ * i18n property list
+ */
+$.i18n = {
+       
+/**
+ * setDictionary()
+ * Initialise the dictionary and translate nodes
+ *
+ * @param property_list i18n_dict : The dictionary to use for translation
+ */
+       setDictionary: function(i18n_dict) {
+               i18n_dict = i18n_dict;
+       },
+       
+/**
+ * _()
+ * The actual translation function. Looks the given string up in the 
+ * dictionary and returns the translation if one exists. If a translation 
+ * is not found, returns the original word
+ *
+ * @param string str : The string to translate 
+ * @param property_list params : params for using printf() on the string
+ * @return string : Translated word
+ *
+ */
+       _: function (str, params) {
+               var transl = str;
+               if (i18n_dict&& i18n_dict[str]) {
+                       transl = i18n_dict[str];
+               }
+               return this.printf(transl, params);
+       },
+       
+/**
+ * toEntity()
+ * Change non-ASCII characters to entity representation 
+ *
+ * @param string str : The string to transform
+ * @return string result : Original string with non-ASCII content converted to entities
+ *
+ */
+       toEntity: function (str) {
+               var result = '';
+               for (var i=0;i<str.length; i++) {
+                       if (str.charCodeAt(i) > 128)
+                               result += "&#"+str.charCodeAt(i)+";";
+                       else
+                               result += str.charAt(i);
+               }
+               return result;
+       },
+       
+/**
+ * stripStr()
+ *
+ * @param string str : The string to strip
+ * @return string result : Stripped string
+ *
+ */
+       stripStr: function(str) {
+               return str.replace(/^\s*/, "").replace(/\s*$/, "");
+       },
+       
+/**
+ * stripStrML()
+ *
+ * @param string str : The multi-line string to strip
+ * @return string result : Stripped string
+ *
+ */
+       stripStrML: function(str) {
+               // Split because m flag doesn't exist before JS1.5 and we need to
+               // strip newlines anyway
+               var parts = str.split('\n');
+               for (var i=0; i<parts.length; i++)
+                       parts[i] = stripStr(parts[i]);
+       
+               // Don't join with empty strings, because it "concats" words
+               // And strip again
+               return stripStr(parts.join(" "));
+       },
+
+/*
+ * printf()
+ * C-printf like function, which substitutes %s with parameters
+ * given in list. %%s is used to escape %s.
+ *
+ * Doesn't work in IE5.0 (splice)
+ *
+ * @param string S : string to perform printf on.
+ * @param string L : Array of arguments for printf()
+ */
+       printf: function(S, L) {
+               if (!L) return S;
+
+               var nS = "";
+               var tS = S.split("%s");
+
+               for(var i=0; i<L.length; i++) {
+                       if (tS[i].lastIndexOf('%') == tS[i].length-1 && i != L.length-1)
+                               tS[i] += "s"+tS.splice(i+1,1)[0];
+                       nS += tS[i] + L[i];
+               }
+               return nS + tS[tS.length-1];
+       }
+
+};
+
+
+})(jQuery);
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/jquery.openid.js b/forum/modules/template_loader.py/forum/skins/default/media/js/jquery.openid.js
new file mode 100644 (file)
index 0000000..a1316c1
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+openid login boxes
+*/
+var providers_large = {
+    google: {
+        name: 'Google',
+        url: 'https://www.google.com/accounts/o8/id'
+    },
+    yahoo: {
+        name: 'Yahoo',      
+        url: 'http://yahoo.com/'
+    },    
+    aol: {
+        name: 'AOL',     
+        label: 'Enter your AOL screenname.',
+        url: 'http://openid.aol.com/{username}'
+    },
+    openid: {
+        name: 'OpenID',     
+        label: 'Enter your OpenID.',
+        url: 'http://'
+    }
+};
+var providers_small = {
+    myopenid: {
+        name: 'MyOpenID',
+        label: 'Enter your MyOpenID username.',
+        url: 'http://{username}.myopenid.com/'
+    },
+    livejournal: {
+        name: 'LiveJournal',
+        label: 'Enter your Livejournal username.',
+        url: 'http://{username}.livejournal.com/'
+    },
+    flickr: {
+        name: 'Flickr',        
+        label: 'Enter your Flickr username.',
+        url: 'http://flickr.com/{username}/'
+    },
+    technorati: {
+        name: 'Technorati',
+        label: 'Enter your Technorati username.',
+        url: 'http://technorati.com/people/technorati/{username}/'
+    },
+    wordpress: {
+        name: 'Wordpress',
+        label: 'Enter your Wordpress.com username.',
+        url: 'http://{username}.wordpress.com/'
+    },
+    blogger: {
+        name: 'Blogger',
+        label: 'Your Blogger account',
+        url: 'http://{username}.blogspot.com/'
+    },
+    verisign: {
+        name: 'Verisign',
+        label: 'Your Verisign username',
+        url: 'http://{username}.pip.verisignlabs.com/'
+    },
+    verisign: {
+        name: 'Verisign',
+        label: 'Your Verisign username',
+        url: 'http://{username}.pip.verisignlabs.com/'
+    },
+    claimid: {
+        name: 'ClaimID',
+        label: 'Your ClaimID username',
+        url: 'http://claimid.com/{username}'
+    }
+};
+var providers = $.extend({}, providers_large, providers_small);
+
+var openid = {
+
+       cookie_expires: 6*30,   // 6 months.
+       cookie_name: 'openid_provider',
+       cookie_path: '/',
+       
+       img_path: '/media/images/openid/',
+       
+       input_id: null,
+       provider_url: null,
+       
+    init: function(input_id) {
+
+        var openid_btns = $('#openid_btns');
+        this.input_id = input_id;
+        
+        $('#openid_choice').show();
+        //$('#openid_input_area').empty();
+        
+        // add box for each provider
+        for (id in providers_large) {
+               openid_btns.append(this.getBoxHTML(providers_large[id], 'large', '.gif'));
+        }
+        if (providers_small) {
+               openid_btns.append('<br/>');
+               for (id in providers_small) {       
+                       openid_btns.append(this.getBoxHTML(providers_small[id], 'small', '.png'));
+               }
+        }
+
+        var box_id = this.readCookie();
+        if (box_id) {
+               this.signin(box_id, true);
+        }  
+    },
+    getBoxHTML: function(provider, box_size, image_ext) {
+            
+        var box_id = provider["name"].toLowerCase();
+        return '<a title="'+provider["name"]+'" href="javascript: openid.signin(\''+ box_id +'\');"' +
+                       ' style="background: #FFF url(' + this.img_path + box_id + image_ext+') no-repeat center center" ' + 'class="' + box_id + ' openid_' + box_size + '_btn"></a>';    
+    
+    },
+    /* Provider image click */
+    signin: function(box_id, onload) {
+       var provider = providers[box_id];
+               if (! provider) {
+                       return;
+               }
+               this.highlight(box_id);
+               this.setCookie(box_id);
+               
+        $('#'+this.input_id).val(provider['url']);
+        var input = $('#'+this.input_id);
+        if(document.selection){
+            var r = document.all.openid_url.createTextRange();
+            var res = r.findText("{username}");
+            if(res)
+                r.select();
+            
+        }
+        else {
+            var text  = input.val();
+            var searchText = "{username}";
+            var posStart = text.indexOf(searchText);
+            if(posStart > -1){
+                input.focus();
+                document.getElementById(this.input_id).setSelectionRange(posStart, posStart + searchText.length);
+            }
+        } 
+    },
+
+    highlight: function (box_id) {
+       // remove previous highlight.
+       var highlight = $('#openid_highlight');
+       if (highlight) {
+               highlight.replaceWith($('#openid_highlight a')[0]);
+       }
+       // add new highlight.
+       $('.'+box_id).wrap('<div id="openid_highlight"></div>');
+    },
+        
+    setCookie: function (value) {
+               var date = new Date();
+               date.setTime(date.getTime()+(this.cookie_expires*24*60*60*1000));
+               var expires = "; expires="+date.toGMTString();
+               document.cookie = this.cookie_name+"="+value+expires+"; path=" + this.cookie_path;
+    },
+        
+    readCookie: function () {
+               var nameEQ = this.cookie_name + "=";
+               var ca = document.cookie.split(';');
+               for(var i=0;i < ca.length;i++) {
+                       var c = ca[i];
+                       while (c.charAt(0)==' ') c = c.substring(1,c.length);
+                       if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
+               }
+               return null;
+    }
+};
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/jquery.validate.pack.js b/forum/modules/template_loader.py/forum/skins/default/media/js/jquery.validate.pack.js
new file mode 100644 (file)
index 0000000..4913450
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * jQuery validation plug-in 1.5
+ *
+ * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
+ * http://docs.jquery.com/Plugins/Validation
+ *
+ * Copyright (c) 2006 - 2008 Jörn Zaefferer
+ *
+ * $Id: jquery.validate.js 5952 2008-11-25 19:12:30Z joern.zaefferer $
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ */
+eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(7($){$.G($.2J,{1y:7(c){l(!6.E){c&&c.2g&&2T.1q&&1q.4Z("3r 2y, 4B\'t 1y, 6d 3r");8}p b=$.16(6[0],\'u\');l(b){8 b}b=1V $.u(c,6[0]);$.16(6[0],\'u\',b);l(b.q.3s){6.4I("1Y, 4E").1t(".4w").4p(7(){b.35=v});6.30(7(a){l(b.q.2g)a.5X();7 24(){l(b.q.3S){b.q.3S.12(b,b.V);8 H}8 v}l(b.35){b.35=H;8 24()}l(b.K()){l(b.1g){b.1v=v;8 H}8 24()}1c{b.2i();8 H}})}8 b},M:7(){l($(6[0]).2H(\'K\')){8 6.1y().K()}1c{p b=H;p a=$(6[0].K).1y();6.O(7(){b|=a.L(6)});8 b}},4L:7(a){p b={},$L=6;$.O(a.1H(/\\s/),7(){b[6]=$L.1G(6);$L.4G(6)});8 b},1b:7(h,k){p f=6[0];l(h){p i=$.16(f.K,\'u\').q;p d=i.1b;p c=$.u.2s(f);2q(h){1e"2o":$.G(c,$.u.1S(k));d[f.r]=c;l(k.J)i.J[f.r]=$.G(i.J[f.r],k.J);31;1e"63":l(!k){R d[f.r];8 c}p e={};$.O(k.1H(/\\s/),7(a,b){e[b]=c[b];R c[b]});8 e}}p g=$.u.3x($.G({},$.u.40(f),$.u.3W(f),$.u.3T(f),$.u.2s(f)),f);l(g.13){p j=g.13;R g.13;g=$.G({13:j},g)}8 g},Y:7(t){8 6.5A(6.2o(t).5w())}});$.G($.5t[":"],{5p:7(a){8!$.2b(a.T)},5m:7(a){8!!$.2b(a.T)},5i:7(a){8!a.3U}});$.1a=7(c,b){l(P.E==1)8 7(){p a=$.48(P);a.52(c);8 $.1a.1I(6,a)};l(P.E>2&&b.2m!=3A){b=$.48(P).4O(1)}l(b.2m!=3A){b=[b]}$.O(b,7(i,n){c=c.3u(1V 3t("\\\\{"+i+"\\\\}","g"),n)});8 c};$.u=7(b,a){6.q=$.G({},$.u.2D,b);6.V=a;6.3q()};$.G($.u,{2D:{J:{},21:{},1b:{},18:"3l",2B:"4H",2i:v,3k:$([]),2A:$([]),3s:v,3j:[],3h:H,4F:7(a){6.3g=a;l(6.q.4D&&!6.4C){6.q.1U&&6.q.1U.12(6,a,6.q.18);6.1E(a).2v()}},4z:7(a){l(!6.1u(a)&&(a.r Z 6.1j||!6.F(a))){6.L(a)}},4t:7(a){l(a.r Z 6.1j||a==6.4q){6.L(a)}},6n:7(a){l(a.r Z 6.1j)6.L(a)},37:7(a,b){$(a).2p(b)},1U:7(a,b){$(a).36(b)}},6g:7(a){$.G($.u.2D,a)},J:{13:"6e 4k 2H 13.",1R:"I 38 6 4k.",1F:"I N a M 1F 65.",1k:"I N a M 62.",1l:"I N a M 1l.",2a:"I N a M 1l (61).",20:"45 44 42 2E 5T¼5S 5R 2E.",1n:"I N a M 1n.",28:"45 44 42 5N 5M 2E.",1O:"I N 5G 1O",2d:"I N a M 5E 5C 1n.",3P:"I N 3O 5v T 5u.",3L:"I N a T 5q a M 5o.",15:$.1a("I N 3K 5n 2O {0} 2R."),1r:$.1a("I N 5k 5h {0} 2R."),2h:$.1a("I N a T 3E {0} 3R {1} 2R 5c."),27:$.1a("I N a T 3E {0} 3R {1}."),1m:$.1a("I N a T 5a 2O 47 43 3D {0}."),1w:$.1a("I N a T 51 2O 47 43 3D {0}.")},4f:H,4Y:{3q:7(){6.26=$(6.q.2A);6.3C=6.26.E&&6.26||$(6.V);6.2k=$(6.q.3k).2o(6.q.2A);6.1j={};6.4S={};6.1g=0;6.1d={};6.1f={};6.1J();p f=(6.21={});$.O(6.q.21,7(d,c){$.O(c.1H(/\\s/),7(a,b){f[b]=d})});p e=6.q.1b;$.O(e,7(b,a){e[b]=$.u.1S(a)});7 1p(a){p b=$.16(6[0].K,"u");b.q["3z"+a.1o]&&b.q["3z"+a.1o].12(b,6[0])}$(6.V).1p("3y 3w 4N",":2F, :4M, :4K, 23, 4J",1p).1p("4p",":3p, :3o",1p);l(6.q.3n)$(6.V).3m("1f-K.1y",6.q.3n)},K:7(){6.3v();$.G(6.1j,6.1z);6.1f=$.G({},6.1z);l(!6.M())$(6.V).2C("1f-K",[6]);6.1h();8 6.M()},3v:7(){6.2G();Q(p i=0,11=(6.1Z=6.11());11[i];i++){6.2n(11[i])}8 6.M()},L:7(a){a=6.2z(a);6.4q=a;6.2N(a);6.1Z=$(a);p b=6.2n(a);l(b){R 6.1f[a.r]}1c{6.1f[a.r]=v}l(!6.3i()){6.14.Y(6.2k)}6.1h();8 b},1h:7(b){l(b){$.G(6.1z,b);6.S=[];Q(p c Z b){6.S.Y({19:b[c],L:6.1X(c)[0]})}6.1i=$.3f(6.1i,7(a){8!(a.r Z b)})}6.q.1h?6.q.1h.12(6,6.1z,6.S):6.3e()},2x:7(){l($.2J.2x)$(6.V).2x();6.1j={};6.2G();6.2W();6.11().36(6.q.18)},3i:7(){8 6.2c(6.1f)},2c:7(a){p b=0;Q(p i Z a)b++;8 b},2W:7(){6.2w(6.14).2v()},M:7(){8 6.3d()==0},3d:7(){8 6.S.E},2i:7(){l(6.q.2i){3c{$(6.3b()||6.S.E&&6.S[0].L||[]).1t(":4A").3a()}39(e){}}},3b:7(){p a=6.3g;8 a&&$.3f(6.S,7(n){8 n.L.r==a.r}).E==1&&a},11:7(){p a=6,2u={};8 $([]).2o(6.V.11).1t(":1Y").1D(":30, :1J, :4y, [4x]").1D(6.q.3j).1t(7(){!6.r&&a.q.2g&&2T.1q&&1q.3l("%o 4v 3K r 4u",6);l(6.r Z 2u||!a.2c($(6).1b()))8 H;2u[6.r]=v;8 v})},2z:7(a){8 $(a)[0]},2t:7(){8 $(6.q.2B+"."+6.q.18,6.3C)},1J:7(){6.1i=[];6.S=[];6.1z={};6.1C=$([]);6.14=$([]);6.1v=H;6.1Z=$([])},2G:7(){6.1J();6.14=6.2t().Y(6.2k)},2N:7(a){6.1J();6.14=6.1E(a)},2n:7(d){d=6.2z(d);l(6.1u(d)){d=6.1X(d.r)[0]}p a=$(d).1b();p c=H;Q(W Z a){p b={W:W,2r:a[W]};3c{p f=$.u.1P[W].12(6,d.T,d,b.2r);l(f=="1T-1Q"){c=v;6m}c=H;l(f=="1d"){6.14=6.14.1D(6.1E(d));8}l(!f){6.4o(d,b);8 H}}39(e){6.q.2g&&2T.1q&&1q.6l("6k 6j 6i 6h L "+d.4n+", 2n 3O \'"+b.W+"\' W");6f e;}}l(c)8;l(6.2c(a))6.1i.Y(d);8 v},4l:7(a,b){l(!$.1x)8;p c=6.q.33?$(a).1x()[6.q.33]:$(a).1x();8 c&&c.J&&c.J[b]},4j:7(a,b){p m=6.q.J[a];8 m&&(m.2m==4i?m:m[b])},4h:7(){Q(p i=0;i<P.E;i++){l(P[i]!==2l)8 P[i]}8 2l},2j:7(a,b){8 6.4h(6.4j(a.r,b),6.4l(a,b),!6.q.3h&&a.6c||2l,$.u.J[b],"<4g>6b: 6a 19 68 Q "+a.r+"</4g>")},4o:7(b,a){p c=6.2j(b,a.W);l(17 c=="7")c=c.12(6,a.2r,b);6.S.Y({19:c,L:b});6.1z[b.r]=c;6.1j[b.r]=c},2w:7(a){l(6.q.1W)a.Y(a.64(6.q.1W));8 a},3e:7(){Q(p i=0;6.S[i];i++){p a=6.S[i];6.q.37&&6.q.37.12(6,a.L,6.q.18);6.2Z(a.L,a.19)}l(6.S.E){6.1C.Y(6.2k)}l(6.q.1s){Q(p i=0;6.1i[i];i++){6.2Z(6.1i[i])}}l(6.q.1U){Q(p i=0,11=6.4e();11[i];i++){6.q.1U.12(6,11[i],6.q.18)}}6.14=6.14.1D(6.1C);6.2W();6.2w(6.1C).4d()},4e:7(){8 6.1Z.1D(6.4c())},4c:7(){8 $(6.S).4b(7(){8 6.L})},2Z:7(a,c){p b=6.1E(a);l(b.E){b.36().2p(6.q.18);b.1G("4a")&&b.49(c)}1c{b=$("<"+6.q.2B+"/>").1G({"Q":6.2Y(a),4a:v}).2p(6.q.18).49(c||"");l(6.q.1W){b=b.2v().4d().60("<"+6.q.1W+">").5Z()}l(!6.26.5Y(b).E)6.q.46?6.q.46(b,$(a)):b.5W(a)}l(!c&&6.q.1s){b.2F("");17 6.q.1s=="1B"?b.2p(6.q.1s):6.q.1s(b)}6.1C.Y(b)},1E:7(a){8 6.2t().1t("[@Q=\'"+6.2Y(a)+"\']")},2Y:7(a){8 6.21[a.r]||(6.1u(a)?a.r:a.4n||a.r)},1u:7(a){8/3p|3o/i.U(a.1o)},1X:7(d){p c=6.V;8 $(5V.5U(d)).4b(7(a,b){8 b.K==c&&b.r==d&&b||41})},1K:7(a,b){2q(b.3Z.3Y()){1e\'23\':8 $("3X:2y",b).E;1e\'1Y\':l(6.1u(b))8 6.1X(b.r).1t(\':3U\').E}8 a.E},3B:7(b,a){8 6.2X[17 b]?6.2X[17 b](b,a):v},2X:{"5Q":7(b,a){8 b},"1B":7(b,a){8!!$(b,a.K).E},"7":7(b,a){8 b(a)}},F:7(a){8!$.u.1P.13.12(6,$.2b(a.T),a)&&"1T-1Q"},3V:7(a){l(!6.1d[a.r]){6.1g++;6.1d[a.r]=v}},4s:7(a,b){6.1g--;l(6.1g<0)6.1g=0;R 6.1d[a.r];l(b&&6.1g==0&&6.1v&&6.K()){$(6.V).30()}1c l(!b&&6.1g==0&&6.1v){$(6.V).2C("1f-K",[6])}},2f:7(a){8 $.16(a,"2f")||$.16(a,"2f",5O={2K:41,M:v,19:6.2j(a,"1R")})}},1M:{13:{13:v},1F:{1F:v},1k:{1k:v},1l:{1l:v},2a:{2a:v},20:{20:v},1n:{1n:v},28:{28:v},1O:{1O:v},2d:{2d:v}},3Q:7(a,b){a.2m==4i?6.1M[a]=b:$.G(6.1M,a)},3W:7(b){p a={};p c=$(b).1G(\'5K\');c&&$.O(c.1H(\' \'),7(){l(6 Z $.u.1M){$.G(a,$.u.1M[6])}});8 a},3T:7(c){p a={};p d=$(c);Q(W Z $.u.1P){p b=d.1G(W);l(b){a[W]=b}}l(a.15&&/-1|5J|5H/.U(a.15)){R a.15}8 a},40:7(a){l(!$.1x)8{};p b=$.16(a.K,\'u\').q.33;8 b?$(a).1x()[b]:$(a).1x()},2s:7(b){p a={};p c=$.16(b.K,\'u\');l(c.q.1b){a=$.u.1S(c.q.1b[b.r])||{}}8 a},3x:7(d,e){$.O(d,7(c,b){l(b===H){R d[c];8}l(b.2V||b.2e){p a=v;2q(17 b.2e){1e"1B":a=!!$(b.2e,e.K).E;31;1e"7":a=b.2e.12(e,e);31}l(a){d[c]=b.2V!==2l?b.2V:v}1c{R d[c]}}});$.O(d,7(a,b){d[a]=$.5F(b)?b(e):b});$.O([\'1r\',\'15\',\'1w\',\'1m\'],7(){l(d[6]){d[6]=2U(d[6])}});$.O([\'2h\',\'27\'],7(){l(d[6]){d[6]=[2U(d[6][0]),2U(d[6][1])]}});l($.u.4f){l(d.1w&&d.1m){d.27=[d.1w,d.1m];R d.1w;R d.1m}l(d.1r&&d.15){d.2h=[d.1r,d.15];R d.1r;R d.15}}l(d.J){R d.J}8 d},1S:7(a){l(17 a=="1B"){p b={};$.O(a.1H(/\\s/),7(){b[6]=v});a=b}8 a},5D:7(c,a,b){$.u.1P[c]=a;$.u.J[c]=b;l(a.E<3){$.u.3Q(c,$.u.1S(c))}},1P:{13:7(b,c,a){l(!6.3B(a,c))8"1T-1Q";2q(c.3Z.3Y()){1e\'23\':p d=$("3X:2y",c);8 d.E>0&&(c.1o=="23-5B"||($.2S.2Q&&!(d[0].5z[\'T\'].5y)?d[0].2F:d[0].T).E>0);1e\'1Y\':l(6.1u(c))8 6.1K(b,c)>0;5x:8 $.2b(b).E>0}},1R:7(e,h,d){l(6.F(h))8"1T-1Q";p g=6.2f(h);l(!6.q.J[h.r])6.q.J[h.r]={};6.q.J[h.r].1R=17 g.19=="7"?g.19(e):g.19;d=17 d=="1B"&&{1k:d}||d;l(g.2K!==e){g.2K=e;p i=6;6.3V(h);p f={};f[h.r]=e;$.2P($.G(v,{1k:d,3N:"2L",3M:"1y"+h.r,5s:"5r",16:f,1s:7(a){l(a){p b=i.1v;i.2N(h);i.1v=b;i.1i.Y(h);i.1h()}1c{p c={};c[h.r]=a||i.2j(h,"1R");i.1h(c)}g.M=a;i.4s(h,a)}},d));8"1d"}1c l(6.1d[h.r]){8"1d"}8 g.M},1r:7(b,c,a){8 6.F(c)||6.1K(b,c)>=a},15:7(b,c,a){8 6.F(c)||6.1K(b,c)<=a},2h:7(b,d,a){p c=6.1K(b,d);8 6.F(d)||(c>=a[0]&&c<=a[1])},1w:7(b,c,a){8 6.F(c)||b>=a},1m:7(b,c,a){8 6.F(c)||b<=a},27:7(b,c,a){8 6.F(c)||(b>=a[0]&&b<=a[1])},1F:7(a,b){8 6.F(b)||/^((([a-z]|\\d|[!#\\$%&\'\\*\\+\\-\\/=\\?\\^X`{\\|}~]|[\\A-\\C\\w-\\B\\x-\\y])+(\\.([a-z]|\\d|[!#\\$%&\'\\*\\+\\-\\/=\\?\\^X`{\\|}~]|[\\A-\\C\\w-\\B\\x-\\y])+)*)|((\\3J)((((\\29|\\1N)*(\\2M\\3I))?(\\29|\\1N)+)?(([\\3H-\\5l\\3G\\3F\\5j-\\5I\\4r]|\\5g|[\\5L-\\5f]|[\\5e-\\5d]|[\\A-\\C\\w-\\B\\x-\\y])|(\\\\([\\3H-\\1N\\3G\\3F\\2M-\\4r]|[\\A-\\C\\w-\\B\\x-\\y]))))*(((\\29|\\1N)*(\\2M\\3I))?(\\29|\\1N)+)?(\\3J)))@((([a-z]|\\d|[\\A-\\C\\w-\\B\\x-\\y])|(([a-z]|\\d|[\\A-\\C\\w-\\B\\x-\\y])([a-z]|\\d|-|\\.|X|~|[\\A-\\C\\w-\\B\\x-\\y])*([a-z]|\\d|[\\A-\\C\\w-\\B\\x-\\y])))\\.)+(([a-z]|[\\A-\\C\\w-\\B\\x-\\y])|(([a-z]|[\\A-\\C\\w-\\B\\x-\\y])([a-z]|\\d|-|\\.|X|~|[\\A-\\C\\w-\\B\\x-\\y])*([a-z]|[\\A-\\C\\w-\\B\\x-\\y])))\\.?$/i.U(a)},1k:7(a,b){8 6.F(b)||/^(5P?|5b):\\/\\/(((([a-z]|\\d|-|\\.|X|~|[\\A-\\C\\w-\\B\\x-\\y])|(%[\\1L-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:)*@)?(((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|((([a-z]|\\d|[\\A-\\C\\w-\\B\\x-\\y])|(([a-z]|\\d|[\\A-\\C\\w-\\B\\x-\\y])([a-z]|\\d|-|\\.|X|~|[\\A-\\C\\w-\\B\\x-\\y])*([a-z]|\\d|[\\A-\\C\\w-\\B\\x-\\y])))\\.)+(([a-z]|[\\A-\\C\\w-\\B\\x-\\y])|(([a-z]|[\\A-\\C\\w-\\B\\x-\\y])([a-z]|\\d|-|\\.|X|~|[\\A-\\C\\w-\\B\\x-\\y])*([a-z]|[\\A-\\C\\w-\\B\\x-\\y])))\\.?)(:\\d*)?)(\\/((([a-z]|\\d|-|\\.|X|~|[\\A-\\C\\w-\\B\\x-\\y])|(%[\\1L-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:|@)+(\\/(([a-z]|\\d|-|\\.|X|~|[\\A-\\C\\w-\\B\\x-\\y])|(%[\\1L-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:|@)*)*)?)?(\\?((([a-z]|\\d|-|\\.|X|~|[\\A-\\C\\w-\\B\\x-\\y])|(%[\\1L-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:|@)|[\\59-\\58]|\\/|\\?)*)?(\\#((([a-z]|\\d|-|\\.|X|~|[\\A-\\C\\w-\\B\\x-\\y])|(%[\\1L-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:|@)|\\/|\\?)*)?$/i.U(a)},1l:7(a,b){8 6.F(b)||!/57|56/.U(1V 55(a))},2a:7(a,b){8 6.F(b)||/^\\d{4}[\\/-]\\d{1,2}[\\/-]\\d{1,2}$/.U(a)},20:7(a,b){8 6.F(b)||/^\\d\\d?\\.\\d\\d?\\.\\d\\d\\d?\\d?$/.U(a)},1n:7(a,b){8 6.F(b)||/^-?(?:\\d+|\\d{1,3}(?:,\\d{3})+)(?:\\.\\d+)?$/.U(a)},28:7(a,b){8 6.F(b)||/^-?(?:\\d+|\\d{1,3}(?:\\.\\d{3})+)(?:,\\d+)?$/.U(a)},1O:7(a,b){8 6.F(b)||/^\\d+$/.U(a)},2d:7(b,e){l(6.F(e))8"1T-1Q";l(/[^0-9-]+/.U(b))8 H;p a=0,d=0,22=H;b=b.3u(/\\D/g,"");Q(n=b.E-1;n>=0;n--){p c=b.54(n);p d=53(c,10);l(22){l((d*=2)>9)d-=9}a+=d;22=!22}8(a%10)==0},3L:7(b,c,a){a=17 a=="1B"?a:"66|67?g|50";8 6.F(c)||b.69(1V 3t(".("+a+")$","i"))},3P:7(b,c,a){8 b==$(a).4X()}}})})(2I);(7($){p c=$.2P;p d={};$.2P=7(a){a=$.G(a,$.G({},$.4W,a));p b=a.3M;l(a.3N=="2L"){l(d[b]){d[b].2L()}8(d[b]=c.1I(6,P))}8 c.1I(6,P)}})(2I);(7($){$.O({3a:\'3y\',4V:\'3w\'},7(b,a){$.1A.32[a]={4U:7(){l($.2S.2Q)8 H;6.4T(b,$.1A.32[a].34,v)},4R:7(){l($.2S.2Q)8 H;6.4Q(b,$.1A.32[a].34,v)},34:7(e){P[0]=$.1A.38(e);P[0].1o=a;8 $.1A.24.1I(6,P)}}});$.G($.2J,{1p:7(d,e,c){8 6.3m(d,7(a){p b=$(a.4m);l(b.2H(e)){8 c.1I(b,P)}})},4P:7(a,b){8 6.2C(a,[$.1A.38({1o:a,4m:b})])}})})(2I);',62,396,'||||||this|function|return|||||||||||||if||||var|settings|name|||validator|true|uF900|uFDF0|uFFEF||u00A0|uFDCF|uD7FF||length|optional|extend|false|Please|messages|form|element|valid|enter|each|arguments|for|delete|errorList|value|test|currentForm|method|_|push|in||elements|call|required|toHide|maxlength|data|typeof|errorClass|message|format|rules|else|pending|case|invalid|pendingRequest|showErrors|successList|submitted|url|date|max|number|type|delegate|console|minlength|success|filter|checkable|formSubmitted|min|metadata|validate|errorMap|event|string|toShow|not|errorsFor|email|attr|split|apply|reset|getLength|da|classRuleSettings|x09|digits|methods|mismatch|remote|normalizeRule|dependency|unhighlight|new|wrapper|findByName|input|currentElements|dateDE|groups|bEven|select|handle||labelContainer|range|numberDE|x20|dateISO|trim|objectLength|creditcard|depends|previousValue|debug|rangelength|focusInvalid|defaultMessage|containers|undefined|constructor|check|add|addClass|switch|parameters|staticRules|errors|rulesCache|hide|addWrapper|resetForm|selected|clean|errorLabelContainer|errorElement|triggerHandler|defaults|ein|text|prepareForm|is|jQuery|fn|old|abort|x0d|prepareElement|than|ajax|msie|characters|browser|window|Number|param|hideErrors|dependTypes|idOrName|showLabel|submit|break|special|meta|handler|cancelSubmit|removeClass|highlight|fix|catch|focus|findLastActive|try|size|defaultShowErrors|grep|lastActive|ignoreTitle|numberOfInvalids|ignore|errorContainer|error|bind|invalidHandler|checkbox|radio|init|nothing|onsubmit|RegExp|replace|checkForm|focusout|normalizeRules|focusin|on|Array|depend|errorContext|to|between|x0c|x0b|x01|x0a|x22|no|accept|port|mode|the|equalTo|addClassRules|and|submitHandler|attributeRules|checked|startRequest|classRules|option|toLowerCase|nodeName|metadataRules|null|Sie|equal|geben|Bitte|errorPlacement|or|makeArray|html|generated|map|invalidElements|show|validElements|autoCreateRanges|strong|findDefined|String|customMessage|field|customMetaMessage|target|id|formatAndAdd|click|lastElement|x7f|stopRequest|onkeyup|assigned|has|cancel|disabled|image|onfocusout|visible|can|blockFocusCleanup|focusCleanup|button|onfocusin|removeAttr|label|find|textarea|file|removeAttrs|password|keyup|slice|triggerEvent|removeEventListener|teardown|valueCache|addEventListener|setup|blur|ajaxSettings|val|prototype|warn|gif|greater|unshift|parseInt|charAt|Date|NaN|Invalid|uF8FF|uE000|less|ftp|long|x7e|x5d|x5b|x21|least|unchecked|x0e|at|x08|filled|more|extension|blank|with|json|dataType|expr|again|same|get|default|specified|attributes|setArray|multiple|card|addMethod|credit|isFunction|only|524288|x1f|2147483647|class|x23|Nummer|eine|previous|https|boolean|Datum|ltiges|gÃ|getElementsByName|document|insertAfter|preventDefault|append|parent|wrap|ISO|URL|remove|parents|address|png|jpe|defined|match|No|Warning|title|returning|This|throw|setDefaults|checking|when|occured|exception|log|continue|onclick'.split('|'),0,{}))
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/osqa.admin.js b/forum/modules/template_loader.py/forum/skins/default/media/js/osqa.admin.js
new file mode 100644 (file)
index 0000000..ee4feed
--- /dev/null
@@ -0,0 +1,73 @@
+$(function() {\r
+    $('.string_list_widget_button').live('click', function() {\r
+        $but = $(this);\r
+\r
+        if ($but.is('.add')) {\r
+            $new = $("<div style=\"display: none;\">" +\r
+                    "<input style=\"width: 600px;\" type=\"text\" name=\"" + $but.attr('name') + "\" value=\"\" />" +\r
+                    "<button class=\"string_list_widget_button\">-</button>" +\r
+                    "</div>");\r
+\r
+            $but.before($new);\r
+            $new.slideDown('fast');\r
+        } else {\r
+            $but.parent().slideUp('fast', function() {\r
+                $but.parent().remove();\r
+            });\r
+        }\r
+\r
+        return false;\r
+    })\r
+\r
+    $('.fieldtool').each(function() {\r
+        var $link = $(this);\r
+        var $input = $link.parent().parent().find('input, textarea');\r
+        var name = $input.attr('name')\r
+\r
+        if ($link.is('.context')) {\r
+            $link.click(function() {\r
+                var $contextbox = $('<input type="text" value="' + name + '" />');\r
+                $link.replaceWith($contextbox);\r
+            });\r
+        } else if ($link.is('.default')) {\r
+            if ($input.length == 1 && ($input.is('[type=text]') || $input.is('textarea'))) {\r
+                $link.click(function() {\r
+                    $.post(name + '/', function(data) {\r
+                        $input.val(data);\r
+                    });\r
+                });\r
+            } else {\r
+                $link.attr('href', name + '/');\r
+            }\r
+        }\r
+    });\r
+\r
+    $('.url_field').each(function() {\r
+        var $input = $(this);\r
+        var $anchor = $input.parent().find('.url_field_anchor');\r
+        var app_url = $anchor.attr('href');\r
+\r
+        function rewrite_anchor() {\r
+            var val = app_url + '/' +  $input.val();\r
+\r
+            $anchor.attr('href', val);\r
+            $anchor.html(val);\r
+\r
+        }\r
+\r
+        $input.keyup(rewrite_anchor);\r
+        rewrite_anchor();        \r
+    });\r
+});\r
+\r
+/*\r
+ * Autocomplete - jQuery plugin 1.0.3\r
+ *\r
+ * Copyright (c) 2007 Dylan Verheul, Dan G. Switzer, Anjesh Tuladhar, Jörn Zaefferer\r
+ *\r
+ * Dual licensed under the MIT and GPL licenses:\r
+ *   http://www.opensource.org/licenses/mit-license.php\r
+ *   http://www.gnu.org/licenses/gpl.html\r
+ *\r
+ */\r
+(function(a){a.fn.extend({autocomplete:function(b,c){var d=typeof b=="string";c=a.extend({},a.Autocompleter.defaults,{url:d?b:null,data:d?null:b,delay:d?a.Autocompleter.defaults.delay:10,max:c&&!c.scroll?10:150},c);c.highlight=c.highlight||function(e){return e};c.formatMatch=c.formatMatch||c.formatItem;return this.each(function(){new a.Autocompleter(this,c)})},result:function(b){return this.bind("result",b)},search:function(b){return this.trigger("search",[b])},flushCache:function(){return this.trigger("flushCache")},setOptions:function(b){return this.trigger("setOptions",[b])},unautocomplete:function(){return this.trigger("unautocomplete")}});a.Autocompleter=function(l,g){var c={UP:38,DOWN:40,DEL:46,TAB:9,RETURN:13,ESC:27,COMMA:188,PAGEUP:33,PAGEDOWN:34,BACKSPACE:8};var b=a(l).attr("autocomplete","off").addClass(g.inputClass);var j;var p="";var m=a.Autocompleter.Cache(g);var e=0;var u;var x={mouseDownOnSelect:false};var r=a.Autocompleter.Select(g,l,d,x);var w;a.browser.opera&&a(l.form).bind("submit.autocomplete",function(){if(w){w=false;return false}});b.bind((a.browser.opera?"keypress":"keydown")+".autocomplete",function(y){u=y.keyCode;switch(y.keyCode){case c.UP:y.preventDefault();if(r.visible()){r.prev()}else{t(0,true)}break;case c.DOWN:y.preventDefault();if(r.visible()){r.next()}else{t(0,true)}break;case c.PAGEUP:y.preventDefault();if(r.visible()){r.pageUp()}else{t(0,true)}break;case c.PAGEDOWN:y.preventDefault();if(r.visible()){r.pageDown()}else{t(0,true)}break;case g.multiple&&a.trim(g.multipleSeparator)==","&&c.COMMA:case c.TAB:case c.RETURN:if(d()){y.preventDefault();w=true;return false}break;case c.ESC:r.hide();break;default:clearTimeout(j);j=setTimeout(t,g.delay);break}}).focus(function(){e++}).blur(function(){e=0;if(!x.mouseDownOnSelect){s()}}).click(function(){if(e++>1&&!r.visible()){t(0,true)}}).bind("search",function(){var y=(arguments.length>1)?arguments[1]:null;function z(D,C){var A;if(C&&C.length){for(var B=0;B<C.length;B++){if(C[B].result.toLowerCase()==D.toLowerCase()){A=C[B];break}}}if(typeof y=="function"){y(A)}else{b.trigger("result",A&&[A.data,A.value])}}a.each(h(b.val()),function(A,B){f(B,z,z)})}).bind("flushCache",function(){m.flush()}).bind("setOptions",function(){a.extend(g,arguments[1]);if("data" in arguments[1]){m.populate()}}).bind("unautocomplete",function(){r.unbind();b.unbind();a(l.form).unbind(".autocomplete")});function d(){var z=r.selected();if(!z){return false}var y=z.result;p=y;if(g.multiple){var A=h(b.val());if(A.length>1){y=A.slice(0,A.length-1).join(g.multipleSeparator)+g.multipleSeparator+y}y+=g.multipleSeparator}b.val(y);v();b.trigger("result",[z.data,z.value]);return true}function t(A,z){if(u==c.DEL){r.hide();return}var y=b.val();if(!z&&y==p){return}p=y;y=i(y);if(y.length>=g.minChars){b.addClass(g.loadingClass);if(!g.matchCase){y=y.toLowerCase()}f(y,k,v)}else{n();r.hide()}}function h(z){if(!z){return[""]}var A=z.split(g.multipleSeparator);var y=[];a.each(A,function(B,C){if(a.trim(C)){y[B]=a.trim(C)}});return y}function i(y){if(!g.multiple){return y}var z=h(y);return z[z.length-1]}function q(y,z){if(g.autoFill&&(i(b.val()).toLowerCase()==y.toLowerCase())&&u!=c.BACKSPACE){b.val(b.val()+z.substring(i(p).length));a.Autocompleter.Selection(l,p.length,p.length+z.length)}}function s(){clearTimeout(j);j=setTimeout(v,200)}function v(){var y=r.visible();r.hide();clearTimeout(j);n();if(g.mustMatch){b.search(function(z){if(!z){if(g.multiple){var A=h(b.val()).slice(0,-1);b.val(A.join(g.multipleSeparator)+(A.length?g.multipleSeparator:""))}else{b.val("")}}})}if(y){a.Autocompleter.Selection(l,l.value.length,l.value.length)}}function k(z,y){if(y&&y.length&&e){n();r.display(y,z);q(z,y[0].value);r.show()}else{v()}}function f(z,B,y){if(!g.matchCase){z=z.toLowerCase()}var A=m.load(z);if(A&&A.length){B(z,A)}else{if((typeof g.url=="string")&&(g.url.length>0)){var C={timestamp:+new Date()};a.each(g.extraParams,function(D,E){C[D]=typeof E=="function"?E():E});a.ajax({mode:"abort",port:"autocomplete"+l.name,dataType:g.dataType,url:g.url,data:a.extend({q:i(z),limit:g.max},C),success:function(E){var D=g.parse&&g.parse(E)||o(E);m.add(z,D);B(z,D)}})}else{r.emptyList();y(z)}}}function o(B){var y=[];var A=B.split("\n");for(var z=0;z<A.length;z++){var C=a.trim(A[z]);if(C){C=C.split("|");y[y.length]={data:C,value:C[0],result:g.formatResult&&g.formatResult(C,C[0])||C[0]}}}return y}function n(){b.removeClass(g.loadingClass)}};a.Autocompleter.defaults={inputClass:"ac_input",resultsClass:"ac_results",loadingClass:"ac_loading",minChars:1,delay:400,matchCase:false,matchSubset:true,matchContains:false,cacheLength:10,max:100,mustMatch:false,extraParams:{},selectFirst:true,formatItem:function(b){return b[0]},formatMatch:null,autoFill:false,width:0,multiple:false,multipleSeparator:", ",highlight:function(c,b){return c.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)("+b.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi,"\\$1")+")(?![^<>]*>)(?![^&;]+;)","gi"),"<strong>$1</strong>")},scroll:true,scrollHeight:180};a.Autocompleter.Cache=function(c){var f={};var d=0;function h(l,k){if(!c.matchCase){l=l.toLowerCase()}var j=l.indexOf(k);if(j==-1){return false}return j==0||c.matchContains}function g(j,i){if(d>c.cacheLength){b()}if(!f[j]){d++}f[j]=i}function e(){if(!c.data){return false}var k={},j=0;if(!c.url){c.cacheLength=1}k[""]=[];for(var m=0,l=c.data.length;m<l;m++){var p=c.data[m];p=(typeof p=="string")?[p]:p;var o=c.formatMatch(p,m+1,c.data.length);if(o===false){continue}var n=o.charAt(0).toLowerCase();if(!k[n]){k[n]=[]}var q={value:o,data:p,result:c.formatResult&&c.formatResult(p)||o};k[n].push(q);if(j++<c.max){k[""].push(q)}}a.each(k,function(r,s){c.cacheLength++;g(r,s)})}setTimeout(e,25);function b(){f={};d=0}return{flush:b,add:g,populate:e,load:function(n){if(!c.cacheLength||!d){return null}if(!c.url&&c.matchContains){var m=[];for(var j in f){if(j.length>0){var o=f[j];a.each(o,function(p,k){if(h(k.value,n)){m.push(k)}})}}return m}else{if(f[n]){return f[n]}else{if(c.matchSubset){for(var l=n.length-1;l>=c.minChars;l--){var o=f[n.substr(0,l)];if(o){var m=[];a.each(o,function(p,k){if(h(k.value,n)){m[m.length]=k}});return m}}}}}return null}}};a.Autocompleter.Select=function(e,j,l,p){var i={ACTIVE:"ac_over"};var k,f=-1,r,m="",s=true,c,o;function n(){if(!s){return}c=a("<div/>").hide().addClass(e.resultsClass).css("position","absolute").appendTo(document.body);o=a("<ul/>").appendTo(c).mouseover(function(t){if(q(t).nodeName&&q(t).nodeName.toUpperCase()=="LI"){f=a("li",o).removeClass(i.ACTIVE).index(q(t));a(q(t)).addClass(i.ACTIVE)}}).click(function(t){a(q(t)).addClass(i.ACTIVE);l();j.focus();return false}).mousedown(function(){p.mouseDownOnSelect=true}).mouseup(function(){p.mouseDownOnSelect=false});if(e.width>0){c.css("width",e.width)}s=false}function q(u){var t=u.target;while(t&&t.tagName!="LI"){t=t.parentNode}if(!t){return[]}return t}function h(t){k.slice(f,f+1).removeClass(i.ACTIVE);g(t);var v=k.slice(f,f+1).addClass(i.ACTIVE);if(e.scroll){var u=0;k.slice(0,f).each(function(){u+=this.offsetHeight});if((u+v[0].offsetHeight-o.scrollTop())>o[0].clientHeight){o.scrollTop(u+v[0].offsetHeight-o.innerHeight())}else{if(u<o.scrollTop()){o.scrollTop(u)}}}}function g(t){f+=t;if(f<0){f=k.size()-1}else{if(f>=k.size()){f=0}}}function b(t){return e.max&&e.max<t?e.max:t}function d(){o.empty();var u=b(r.length);for(var v=0;v<u;v++){if(!r[v]){continue}var w=e.formatItem(r[v].data,v+1,u,r[v].value,m);if(w===false){continue}var t=a("<li/>").html(e.highlight(w,m)).addClass(v%2==0?"ac_even":"ac_odd").appendTo(o)[0];a.data(t,"ac_data",r[v])}k=o.find("li");if(e.selectFirst){k.slice(0,1).addClass(i.ACTIVE);f=0}if(a.fn.bgiframe){o.bgiframe()}}return{display:function(u,t){n();r=u;m=t;d()},next:function(){h(1)},prev:function(){h(-1)},pageUp:function(){if(f!=0&&f-8<0){h(-f)}else{h(-8)}},pageDown:function(){if(f!=k.size()-1&&f+8>k.size()){h(k.size()-1-f)}else{h(8)}},hide:function(){c&&c.hide();k&&k.removeClass(i.ACTIVE);f=-1},visible:function(){return c&&c.is(":visible")},current:function(){return this.visible()&&(k.filter("."+i.ACTIVE)[0]||e.selectFirst&&k[0])},show:function(){var v=a(j).offset();c.css({width:typeof e.width=="string"||e.width>0?e.width:a(j).width(),top:v.top+j.offsetHeight,left:v.left}).show();if(e.scroll){o.scrollTop(0);o.css({maxHeight:e.scrollHeight,overflow:"auto"});if(a.browser.msie&&typeof document.body.style.maxHeight==="undefined"){var t=0;k.each(function(){t+=this.offsetHeight});var u=t>e.scrollHeight;o.css("height",u?e.scrollHeight:t);if(!u){k.width(o.width()-parseInt(k.css("padding-left"))-parseInt(k.css("padding-right")))}}}},selected:function(){var t=k&&k.filter("."+i.ACTIVE).removeClass(i.ACTIVE);return t&&t.length&&a.data(t[0],"ac_data")},emptyList:function(){o&&o.empty()},unbind:function(){c&&c.remove()}}};a.Autocompleter.Selection=function(d,e,c){if(d.setSelectionRange){d.setSelectionRange(e,c)}else{if(d.createTextRange){var b=d.createTextRange();b.collapse(true);b.moveStart("character",e);b.moveEnd("character",c);b.select()}else{if(d.selectionStart){d.selectionStart=e;d.selectionEnd=c}}}d.focus()}})(jQuery);\r
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/osqa.ask.js b/forum/modules/template_loader.py/forum/skins/default/media/js/osqa.ask.js
new file mode 100644 (file)
index 0000000..4bf05be
--- /dev/null
@@ -0,0 +1,94 @@
+var currentSideBar = 'div#title_side_bar';
+function changeSideBar(enabled_bar) {
+    $(currentSideBar).hide();
+    currentSideBar = enabled_bar;
+    $(currentSideBar).fadeIn('slow');
+
+}
+
+$(function () {
+    $('div#editor_side_bar').hide();
+    $('div#tags_side_bar').hide();
+
+    $('#id_title').focus(function(){changeSideBar('div#title_side_bar')});
+    $('#editor').focus(function(){changeSideBar('div#editor_side_bar')});
+    $('#id_tags').focus(function(){changeSideBar('div#tags_side_bar')});
+});
+
+$(function() {
+    var $input = $('#id_title');
+    var $box = $('#ask-related-questions');
+    var template = $('#question-summary-template').html();
+
+    var results_cache = {};
+
+    function reload_suggestions_box(e) {
+        var relatedQuestionsDiv = $('#ask-related-questions');
+        var q = $input.val().replace(/^\s+|\s+$/g,"");
+
+        if(q.length == 0) {
+            close_suggestions_box();
+            relatedQuestionsDiv.html('');
+            return false;
+        } else if(relatedQuestionsDiv[0].style.height == 0 || relatedQuestionsDiv[0].style.height == '0px') {
+            relatedQuestionsDiv.animate({'height':'150'}, 350);
+        }
+
+        if (results_cache[q] && results_cache[q] != '') {
+            relatedQuestionsDiv.html(results_cache[q]);
+            return false;
+        }
+
+        $.post(related_questions_url, {title: q}, function(data) {
+            if (data) {
+                var c = $input.val().replace(/^\s+|\s+$/g,"");
+
+                if (c != q) {
+                    return;
+                }
+
+                if(data.length == 0) {
+                    relatedQuestionsDiv.html('<br /><br /><div align="center">No questions like this have been found.</div>');
+                    return;
+                }
+
+                var html = '';
+                for (var i = 0; i < data.length; i++) {
+                    var item = template.replace(new RegExp('%URL%', 'g'), data[i].url)
+                                       .replace(new RegExp('%SCORE%', 'g'), data[i].score)
+                                       .replace(new RegExp('%TITLE%', 'g'), data[i].title)
+                                       .replace(new RegExp('%SUMMARY%', 'g'), data[i].summary);
+
+                    html += item;
+
+                }
+
+                results_cache[q] = html;
+
+                relatedQuestionsDiv.html(html);
+            }
+        }, 'json');
+
+        return false;
+    }
+
+    function close_suggestions_box() {
+        $('#ask-related-questions').animate({'height':'0'},350, function() {
+            $('#ask-related-questions').html('');
+        });
+    }
+
+    $input.keyup(reload_suggestions_box);
+    $input.focus(reload_suggestions_box);
+    $input.blur(close_suggestions_box);
+
+    // for chrome
+    $input.keydown(focus_on_question);
+    function focus_on_question(e) {
+        var is_chrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;
+
+        if(e.keyCode == 9 && is_chrome) {
+            $('#editor')[0].focus();
+        }
+    }
+});
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/osqa.main.js b/forum/modules/template_loader.py/forum/skins/default/media/js/osqa.main.js
new file mode 100644 (file)
index 0000000..31271d1
--- /dev/null
@@ -0,0 +1,1156 @@
+var response_commands = {\r
+    refresh_page: function() {\r
+        window.location.reload(true)\r
+    },\r
+    \r
+    update_post_score: function(id, inc) {\r
+        var $score_board = $('#post-' + id + '-score');\r
+        var current = parseInt($score_board.html())\r
+        if (isNaN(current)){\r
+            current = 0;\r
+        }\r
+        $score_board.html(current + inc)\r
+    },\r
+\r
+    update_user_post_vote: function(id, vote_type) {\r
+        var $upvote_button = $('#post-' + id + '-upvote');\r
+        var $downvote_button = $('#post-' + id + '-downvote');\r
+\r
+        $upvote_button.removeClass('on');\r
+        $downvote_button.removeClass('on');\r
+\r
+        if (vote_type == 'up') {\r
+            $upvote_button.addClass('on');\r
+        } else if (vote_type == 'down') {\r
+            $downvote_button.addClass('on');\r
+        }\r
+    },\r
+\r
+    update_favorite_count: function(inc) {\r
+        var $favorite_count = $('#favorite-count');\r
+        var count = parseInt($favorite_count.html());\r
+\r
+        if (isNaN(count))\r
+            count = 0;\r
+\r
+        count += inc;\r
+\r
+        if (count == 0)\r
+            count = '';\r
+\r
+        $favorite_count.html(count);\r
+    },\r
+\r
+    update_favorite_mark: function(type) {\r
+        if (type == 'on') {\r
+            $('#favorite-mark').addClass('on');\r
+        } else {\r
+            $('#favorite-mark').removeClass('on');\r
+        }\r
+    },\r
+\r
+    mark_accepted: function(id) {        \r
+        var $answer = $('#answer-container-' + id);\r
+        $answer.addClass('accepted-answer');\r
+        $answer.find('.accept-answer').addClass('on');\r
+        $answer.find('.accept-answer').attr('title', $answer.find('.accept-answer').attr('bn:on'));\r
+    },\r
+\r
+    unmark_accepted: function(id) {\r
+        var $answer = $('#answer-container-' + id);\r
+        $answer.removeClass('accepted-answer');\r
+        $answer.find('.accept-answer').removeClass('on');\r
+        $answer.find('.accept-answer').attr('title', $answer.find('.accept-answer').attr('bn:off'));\r
+    },\r
+\r
+    remove_comment: function(id) {\r
+        var $comment = $('#comment-' + id);\r
+        $comment.css('background', 'red')\r
+        $comment.fadeOut('slow', function() {\r
+            $comment.remove();    \r
+        });\r
+    },\r
+\r
+    insert_comment: function(post_id, comment_id, comment, username, profile_url, delete_url, edit_url, convert_url) {\r
+        var $container = $('#comments-container-' + post_id);\r
+        var skeleton = $('#new-comment-skeleton-' + post_id).html().toString();\r
+\r
+        skeleton = skeleton.replace(new RegExp('%ID%', 'g'), comment_id)\r
+                .replace(new RegExp('%COMMENT%', 'g'), comment)\r
+                .replace(new RegExp('%USERNAME%', 'g'), username)\r
+                .replace(new RegExp('%PROFILE_URL%', 'g'), profile_url)\r
+                .replace(new RegExp('%DELETE_URL%', 'g'), delete_url)\r
+                .replace(new RegExp('%EDIT_URL%', 'g'), edit_url)\r
+                .replace(new RegExp('%CONVERT_URL%', 'g'), convert_url);\r
+\r
+        $container.append(skeleton);\r
+\r
+        $('#comment-' + comment_id).slideDown('slow');\r
+    },\r
+\r
+    update_comment: function(comment_id, comment_text) {\r
+        var $comment = $('#comment-' + comment_id);\r
+        $comment.find('.comment-text').html(comment_text);\r
+\r
+        $comment.slideDown('slow');\r
+    },\r
+\r
+    mark_deleted: function(post_type, post_id) {\r
+        if (post_type == 'answer') {\r
+            var $answer = $('#answer-container-' + post_id);\r
+            $answer.addClass('deleted');\r
+        } else {\r
+            var $container = $('#question-table');\r
+            $container.addClass('deleted');\r
+        }\r
+    },\r
+\r
+    unmark_deleted: function(post_type, post_id) {\r
+        if (post_type == 'answer') {\r
+            var $answer = $('#answer-container-' + post_id);\r
+            $answer.removeClass('deleted');\r
+        } else {\r
+            var $container = $('#question-table');\r
+            $container.removeClass('deleted');\r
+        }\r
+    },\r
+\r
+    set_subscription_button: function(text) {\r
+        $('.subscription_switch').html(text);\r
+    },\r
+\r
+    set_subscription_status: function(text) {\r
+        $('.subscription-status').html(text);\r
+    }\r
+}\r
+\r
+function show_dialog (extern) {\r
+    var default_close_function = function($diag) {\r
+        $diag.fadeOut('fast', function() {\r
+            $diag.remove();\r
+        });\r
+    }\r
+\r
+    var options = {\r
+        extra_class: '',\r
+        pos: {\r
+            x: ($(window).width() / 2) + $(window).scrollLeft(),\r
+            y: ($(window).height() / 2) + $(window).scrollTop()\r
+        },\r
+        dim: false, \r
+        yes_text: messages.ok,\r
+        yes_callback: default_close_function,\r
+        no_text: messages.cancel,\r
+        show_no: false,\r
+        close_on_clickoutside: false\r
+    }\r
+\r
+    $.extend(options, extern);\r
+\r
+    if (options.event != undefined) {\r
+        options.pos = {x: options.event.pageX, y: options.event.pageY};\r
+    }\r
+\r
+    var html = '<div class="dialog ' + options.extra_class + '" style="display: none;">'\r
+             + '<div class="dialog-content">' + options.html + '</div><div class="dialog-buttons">';\r
+\r
+    if (options.show_no) {\r
+        html += '<button class="dialog-no">' + options.no_text + '</button>';\r
+    }\r
+\r
+    html += '<button class="dialog-yes">' + options.yes_text + '</button>'\r
+            + '</div></div>';\r
+\r
+    $dialog = $(html);\r
+    $('body').append($dialog);\r
+    var message = $('.dialog-content')[0];\r
+    message.style.visibility = "hidden";\r
+\r
+    if (options.dim === false) {\r
+        $dialog.css({\r
+            visibility: 'hidden',\r
+            display: 'block'\r
+        });\r
+\r
+        options.dim = {w: $dialog.width(), h: $dialog.height()};\r
+\r
+        $dialog.css({\r
+            width: 1,\r
+            height: 1,\r
+            visibility: 'visible'\r
+        });\r
+    }\r
+\r
+    $dialog.css({\r
+        top: options.pos.y,\r
+        left: options.pos.x\r
+    });\r
+    \r
+    top_position_change = (options.dim.h / 2)\r
+    left_position_change = (options.dim.w / 2)\r
+    \r
+    new_top_position = options.pos.y - top_position_change\r
+    new_left_position = options.pos.x - left_position_change\r
+    \r
+    if (new_left_position < 0) {\r
+        left_position_change = 0\r
+    }\r
+    if (($(window).scrollTop() - new_top_position) > 0) {\r
+        top_position_change = 0\r
+    }\r
+    if ((options.event.pageY + options.dim.h) > ($(window).height() + $(window).scrollTop())) {\r
+        top_position_change = options.dim.h\r
+    }\r
+    if ((options.event.pageX + options.dim.w) > ($(window).width() + $(window).scrollLeft())) {\r
+        left_position_change = options.dim.w\r
+    }\r
+    \r
+    $dialog.animate({\r
+        top: "-=" + top_position_change,\r
+        left: "-=" + left_position_change,\r
+        width: options.dim.w,\r
+        height: options.dim.h\r
+    }, 200, function() {\r
+        message.style.visibility = "visible";\r
+    });\r
+\r
+    $dialog.find('.dialog-no').click(function() {\r
+        default_close_function($dialog);\r
+    });\r
+\r
+    $dialog.find('.dialog-yes').click(function() {\r
+        options.yes_callback($dialog);\r
+    });\r
+\r
+    if (options.close_on_clickoutside) {\r
+        $dialog.one('clickoutside', function() {\r
+            default_close_function($dialog);\r
+        });\r
+    }\r
+\r
+    return $dialog;\r
+}\r
+\r
+function show_message(evt, msg, callback) {\r
+    var $dialog = show_dialog({\r
+        html: msg,\r
+        extra_class: 'warning',\r
+        event: evt,\r
+        yes_callback: function() {\r
+            $dialog.fadeOut('fast', function() {\r
+                $dialog.remove();\r
+            });\r
+            if (callback) {\r
+                callback();\r
+            }\r
+        },\r
+        close_on_clickoutside: true\r
+    });\r
+}\r
+\r
+function load_prompt(evt, el, url) {\r
+    $.get(url, function(data) {\r
+        var doptions = {\r
+         html: data,\r
+            extra_class: 'prompt',\r
+            yes_callback: function() {\r
+                var postvars = {};\r
+                $dialog.find('input, textarea, select').each(function() {\r
+                    postvars[$(this).attr('name')] = $(this).val();\r
+                });\r
+                $.post(url, postvars, function(data) {\r
+                    $dialog.fadeOut('fast', function() {\r
+                        $dialog.remove();\r
+                    });\r
+                    process_ajax_response(data, evt);\r
+                }, 'json');\r
+            },\r
+            show_no: true\r
+        }\r
+\r
+        if (!el.is('.centered')) {\r
+            doptions.event = evt;\r
+        }\r
+\r
+        var $dialog = show_dialog(doptions);\r
+    });\r
+}\r
+\r
+function process_ajax_response(data, evt, callback) {\r
+    if (!data.success && data['error_message'] != undefined) {\r
+        show_message(evt, data.error_message, function() {if (callback) callback(true);});\r
+        end_command(false);\r
+    } else if (typeof data['commands'] != undefined){\r
+        for (var command in data.commands) {\r
+            response_commands[command].apply(null, data.commands[command])\r
+\r
+\r
+        }\r
+\r
+        if (data['message'] != undefined) {\r
+            show_message(evt, data.message, function() {if (callback) callback(false);})\r
+        } else {\r
+            if (callback) callback(false);\r
+        }\r
+        end_command(true);\r
+    }\r
+}\r
+\r
+var running = false;\r
+\r
+function start_command() {\r
+    $('body').append($('<div id="command-loader"></div>'));\r
+    running = true;\r
+}\r
+\r
+function end_command(success) {\r
+    if (success) {\r
+        $('#command-loader').addClass('success');\r
+        $('#command-loader').fadeOut("slow", function() {\r
+            $('#command-loader').remove();\r
+            running = false;\r
+        });\r
+    } else {\r
+        $('#command-loader').remove();\r
+        running = false;\r
+    }\r
+}\r
+\r
+$(function() {\r
+    $('a.ajax-command').live('click', function(evt) {\r
+        if (running) return false;\r
+\r
+        $('.context-menu-dropdown').slideUp('fast');\r
+\r
+        var el = $(this);\r
+\r
+        if (el.is('.withprompt')) {\r
+            load_prompt(evt, el, el.attr('href'));\r
+        } else if(el.is('.confirm')) {\r
+            var doptions = {\r
+                html: messages.confirm,\r
+                extra_class: 'confirm',\r
+                yes_callback: function() {\r
+                    start_command();\r
+                    $.getJSON(el.attr('href'), function(data) {\r
+                        process_ajax_response(data, evt);\r
+                        $dialog.fadeOut('fast', function() {\r
+                            $dialog.remove();\r
+                        });\r
+                    });\r
+                },\r
+                yes_text: messages.yes,\r
+                show_no: true,\r
+                no_text: messages.no\r
+            }\r
+\r
+            if (!el.is('.centered')) {\r
+                doptions.event = evt;\r
+            }\r
+            var $dialog = show_dialog(doptions);\r
+        } else {\r
+            start_command();\r
+            $.getJSON(el.attr('href'), function(data) {\r
+                process_ajax_response(data, evt);\r
+            });\r
+        }\r
+\r
+        return false\r
+    });\r
+\r
+    $('.context-menu').each(function() {\r
+        var $menu = $(this);\r
+        var $trigger = $menu.find('.context-menu-trigger');\r
+        var $dropdown = $menu.find('.context-menu-dropdown');\r
+\r
+        $trigger.click(function() {\r
+            $dropdown.slideToggle('fast', function() {\r
+                if ($dropdown.is(':visible')) {\r
+                   $dropdown.one('clickoutside', function() {\r
+                       if ($dropdown.is(':visible'))\r
+                            $dropdown.slideUp('fast');\r
+                    });\r
+                }\r
+            });    \r
+        });\r
+    });\r
+\r
+    $('div.comment-form-container').each(function() {\r
+        var $container = $(this);\r
+        var $comment_tools = $container.parent().find('.comment-tools');\r
+        var $comments_container = $container.parent().find('.comments-container');\r
+        \r
+        var $form = $container.find('form');\r
+\r
+        if ($form.length) {\r
+            var $textarea = $container.find('textarea');\r
+            var textarea = $textarea.get(0);\r
+            var $button = $container.find('.comment-submit');\r
+            var $cancel = $container.find('.comment-cancel');\r
+            var $chars_left_message = $container.find('.comments-chars-left-msg');\r
+            var $chars_togo_message = $container.find('.comments-chars-togo-msg');\r
+            var $chars_counter = $container.find('.comments-char-left-count');\r
+\r
+            var $add_comment_link = $comment_tools.find('.add-comment-link');\r
+\r
+            var chars_limits = $chars_counter.html().split('|');\r
+\r
+            var min_length = parseInt(chars_limits[0]);\r
+            var max_length = parseInt(chars_limits[1]);\r
+\r
+            var warn_length = max_length - 30;\r
+            var current_length = 0;\r
+            var comment_in_form = false;\r
+            var interval = null;\r
+\r
+            var hcheck = !($.browser.msie || $.browser.opera);\r
+\r
+            $textarea.css("padding-top", 0).css("padding-bottom", 0).css("resize", "none");\r
+            textarea.style.overflow = 'hidden';\r
+\r
+\r
+            function cleanup_form() {\r
+                $textarea.val('');\r
+                $textarea.css('height', 80);\r
+                $chars_counter.html(max_length);\r
+                $chars_left_message.removeClass('warn');\r
+                comment_in_form = false;\r
+                current_length = 0;\r
+\r
+                $chars_left_message.hide();\r
+                $chars_togo_message.show();\r
+\r
+                $chars_counter.removeClass('warn');\r
+                $chars_counter.html(min_length);\r
+                $button.attr("disabled","disabled");\r
+\r
+                interval = null;\r
+            }\r
+\r
+            cleanup_form();\r
+\r
+            function process_form_changes() {\r
+                var length = $textarea.val().replace(/[ ]{2,}/g," ").length;\r
+\r
+                if (current_length == length)\r
+                    return;\r
+\r
+                if (length < warn_length && current_length >= warn_length) {\r
+                    $chars_counter.removeClass('warn');\r
+                } else if (current_length < warn_length && length >= warn_length){\r
+                    $chars_counter.addClass('warn');\r
+                }\r
+\r
+                if (length < min_length) {\r
+                    $chars_left_message.hide();\r
+                    $chars_togo_message.show();\r
+                    $chars_counter.html(min_length - length);\r
+                } else {\r
+                    length = $textarea.val().length;\r
+                    $chars_togo_message.hide();\r
+                    $chars_left_message.show();\r
+                    $chars_counter.html(max_length - length);\r
+                }\r
+\r
+                if (length > max_length || length < min_length) {\r
+                    $button.attr("disabled","disabled");\r
+                } else {\r
+                    $button.removeAttr("disabled");\r
+                }\r
+\r
+                var current_height = textarea.style.height;\r
+                if (hcheck)\r
+                    textarea.style.height = "0px";\r
+\r
+                var h = Math.max(80, textarea.scrollHeight);\r
+                textarea.style.height = current_height;\r
+                $textarea.animate({height: h + 'px'}, 50);\r
+\r
+                current_length = length;\r
+            }\r
+\r
+            function show_comment_form() {\r
+                $container.slideDown('slow');\r
+                $add_comment_link.fadeOut('slow');\r
+                $textarea.focus();\r
+                interval = window.setInterval(function() {\r
+                    process_form_changes();\r
+                }, 200);\r
+            }\r
+\r
+            function hide_comment_form() {\r
+                if (interval != null) {\r
+                    window.clearInterval(interval);\r
+                    interval = null;\r
+                }\r
+                $container.slideUp('slow');\r
+                $add_comment_link.fadeIn('slow');\r
+            }\r
+\r
+            $add_comment_link.click(function(){\r
+                cleanup_form();\r
+                show_comment_form();\r
+                return false;\r
+            });\r
+\r
+            $('#' + $comments_container.attr('id') + ' .comment-edit').live('click', function() {\r
+                var $link = $(this);\r
+                var comment_id = /comment-(\d+)-edit/.exec($link.attr('id'))[1];\r
+                var $comment = $('#comment-' + comment_id);\r
+\r
+                comment_in_form = comment_id;\r
+\r
+                $.get($link.attr('href'), function(data) {\r
+                    $textarea.val(data);\r
+                });\r
+\r
+                $comment.slideUp('slow');\r
+                show_comment_form();\r
+                return false;\r
+            });\r
+\r
+            $button.click(function(evt) {\r
+                if (running) return false;\r
+\r
+                var post_data = {\r
+                    comment: $textarea.val()\r
+                }\r
+\r
+                if (comment_in_form) {\r
+                    post_data['id'] = comment_in_form;\r
+                }\r
+\r
+                start_command();\r
+                $.post($form.attr('action'), post_data, function(data) {\r
+                    process_ajax_response(data, evt, function(error) {\r
+                        if (!error) {\r
+                            cleanup_form();\r
+                            hide_comment_form();\r
+                        }\r
+                    });\r
+\r
+                }, "json");\r
+\r
+                return false;\r
+            });\r
+\r
+            $cancel.click(function(event) {\r
+                if (confirm("You will lose all of your changes in this comment.  Do you still wish to proceed?")){\r
+                    if (comment_in_form) {\r
+                        $comment = $('#comment-' + comment_in_form).slideDown('slow');\r
+                    }\r
+                    hide_comment_form();\r
+                    cleanup_form();\r
+                }\r
+                return false;\r
+            });\r
+        }\r
+\r
+        $comment_tools.find('.show-all-comments-link').click(function() {\r
+            $comments_container.find('.not_top_scorer').slideDown('slow');\r
+            $(this).fadeOut('slow');\r
+            $comment_tools.find('.comments-showing').fadeOut('slow');\r
+            return false;\r
+        });\r
+    });\r
+\r
+    if ($('#editor').length) {\r
+        var $editor = $('#editor');\r
+        var $previewer = $('#previewer');\r
+        var $container = $('#editor-metrics');\r
+\r
+        var initial_whitespace_rExp = /^[^A-Za-z0-9]+/gi;\r
+        var non_alphanumerics_rExp = rExp = /[^A-Za-z0-9]+/gi;\r
+        var editor_interval = null;\r
+\r
+        $editor.focus(function() {\r
+            if (editor_interval == null) {\r
+                editor_interval = window.setInterval(function() {\r
+                    recalc_metrics();\r
+                }, 200);\r
+            }\r
+        });\r
+\r
+        function recalc_metrics() {\r
+            var text = $previewer.text();\r
+\r
+            var char_count = text.length;\r
+            var fullStr = text + " ";\r
+            var left_trimmedStr = fullStr.replace(initial_whitespace_rExp, "");\r
+            var cleanedStr = left_trimmedStr.replace(non_alphanumerics_rExp, " ");\r
+            var splitString = cleanedStr.split(" ");\r
+            var word_count = splitString.length - 1;\r
+\r
+            var metrics = char_count + " " + (char_count == 1 ? messages.character : messages.characters);\r
+            metrics += " / " + word_count + " " + (word_count == 1 ? messages.word : messages.words);\r
+            $container.html(metrics);\r
+        }\r
+    }\r
+});\r
+\r
+//var scriptUrl, interestingTags, ignoredTags, tags, $;\r
+function pickedTags(){\r
+\r
+    var sendAjax = function(tagname, reason, action, callback){\r
+        var url = scriptUrl;\r
+        if (action == 'add'){\r
+            url += $.i18n._('mark-tag/');\r
+            if (reason == 'good'){\r
+                url += $.i18n._('interesting/');\r
+            }\r
+            else {\r
+                url += $.i18n._('ignored/');\r
+            }\r
+        }\r
+        else {\r
+            url += $.i18n._('unmark-tag/');\r
+        }\r
+        url = url + tagname + '/';\r
+\r
+        var call_settings = {\r
+            type:'POST',\r
+            url:url,\r
+            data: ''\r
+        };\r
+        if (callback !== false){\r
+            call_settings.success = callback;\r
+        }\r
+        $.ajax(call_settings);\r
+    };\r
+\r
+\r
+    var unpickTag = function(from_target ,tagname, reason, send_ajax){\r
+        //send ajax request to delete tag\r
+        var deleteTagLocally = function(){\r
+            from_target[tagname].remove();\r
+            delete from_target[tagname];\r
+        };\r
+        if (send_ajax){\r
+            sendAjax(tagname,reason,'remove',deleteTagLocally);\r
+        }\r
+        else {\r
+            deleteTagLocally();\r
+        }\r
+\r
+    };\r
+\r
+    var setupTagDeleteEvents = function(obj,tag_store,tagname,reason,send_ajax){\r
+        obj.unbind('mouseover').bind('mouseover', function(){\r
+            $(this).attr('src', mediaUrl('media/images/close-small-hover.png'));\r
+        });\r
+        obj.unbind('mouseout').bind('mouseout', function(){\r
+            $(this).attr('src', mediaUrl('media/images/close-small-dark.png'));\r
+        });\r
+        obj.click( function(){\r
+            unpickTag(tag_store,tagname,reason,send_ajax);\r
+        });\r
+    };\r
+\r
+    var handlePickedTag = function(obj,reason){\r
+        var tagname = $.trim($(obj).prev().attr('value'));\r
+        var to_target = interestingTags;\r
+        var from_target = ignoredTags;\r
+        var to_tag_container;\r
+        if (reason == 'bad'){\r
+            to_target = ignoredTags;\r
+            from_target = interestingTags;\r
+            to_tag_container = $('div .tags.ignored');\r
+        }\r
+        else if (reason != 'good'){\r
+            return;\r
+        }\r
+        else {\r
+            to_tag_container = $('div .tags.interesting');\r
+        }\r
+\r
+        if (tagname in from_target){\r
+            unpickTag(from_target,tagname,reason,false);\r
+        }\r
+\r
+        if (!(tagname in to_target)){\r
+            //send ajax request to pick this tag\r
+\r
+            sendAjax(tagname,reason,'add',function(){\r
+                var new_tag = $('<span></span>');\r
+                new_tag.addClass('deletable-tag');\r
+                var tag_link = $('<a></a>');\r
+                tag_link.attr('rel','tag');\r
+                tag_link.attr('href', scriptUrl + $.i18n._('tags/') + tagname + '/');\r
+                tag_link.html(tagname);\r
+                var del_link = $('<img></img>');\r
+                del_link.addClass('delete-icon');\r
+                del_link.attr('src', mediaUrl('media/images/close-small-dark.png'));\r
+\r
+                setupTagDeleteEvents(del_link, to_target, tagname, reason, true);\r
+\r
+                new_tag.append(tag_link);\r
+                new_tag.append(del_link);\r
+                to_tag_container.append(new_tag);\r
+\r
+                to_target[tagname] = new_tag;\r
+            });\r
+        }\r
+    };\r
+\r
+    var collectPickedTags = function(){\r
+        var good_prefix = 'interesting-tag-';\r
+        var bad_prefix = 'ignored-tag-';\r
+        var good_re = RegExp('^' + good_prefix);\r
+        var bad_re = RegExp('^' + bad_prefix);\r
+        interestingTags = {};\r
+        ignoredTags = {};\r
+        $('.deletable-tag').each(\r
+            function(i,item){\r
+                var item_id = $(item).attr('id');\r
+                var tag_name, tag_store;\r
+                if (good_re.test(item_id)){\r
+                    tag_name = item_id.replace(good_prefix,'');\r
+                    tag_store = interestingTags;\r
+                    reason = 'good';\r
+                }\r
+                else if (bad_re.test(item_id)){\r
+                    tag_name = item_id.replace(bad_prefix,'');\r
+                    tag_store = ignoredTags;\r
+                    reason = 'bad';\r
+                }\r
+                else {\r
+                    return;\r
+                }\r
+                tag_store[tag_name] = $(item);\r
+                setupTagDeleteEvents($(item).find('img'),tag_store,tag_name,reason,true);\r
+            }\r
+        );\r
+    };\r
+\r
+    var setupHideIgnoredQuestionsControl = function(){\r
+        $('#hideIgnoredTagsCb').unbind('click').click(function(){\r
+            $.ajax({\r
+                        type: 'POST',\r
+                        dataType: 'json',\r
+                        cache: false,\r
+                        url: scriptUrl + $.i18n._('command/'),\r
+                        data: {command:'toggle-ignored-questions'}\r
+                    });\r
+        });\r
+    };\r
+    return {\r
+        init: function(){\r
+            collectPickedTags();\r
+            setupHideIgnoredQuestionsControl();\r
+            $("#interestingTagInput, #ignoredTagInput").autocomplete(messages.matching_tags_url, {\r
+                minChars: 1,\r
+                matchContains: true,\r
+                max: 20,\r
+                /*multiple: false, - the favorite tags and ignore tags don't let you do multiple tags\r
+                multipleSeparator: " "*/\r
+\r
+                formatItem: function(row, i, max, value) {\r
+                    return row[1] + " (" + row[2] + ")";\r
+                },\r
+\r
+                formatResult: function(row, i, max, value){\r
+                    return row[1];\r
+                }\r
+\r
+            });\r
+            $("#interestingTagAdd").click(function(){handlePickedTag(this,'good');});\r
+            $("#ignoredTagAdd").click(function(){handlePickedTag(this,'bad');});\r
+        }\r
+    };\r
+}\r
+\r
+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()}}}};\r
+\r
+var mediaUrl = function(resource){\r
+    return scriptUrl + 'm/' + osqaSkin + '/' + resource;\r
+};\r
+\r
+/*\r
+ * jQuery i18n plugin\r
+ * @requires jQuery v1.1 or later\r
+ *\r
+ * Examples at: http://recurser.com/articles/2008/02/21/jquery-i18n-translation-plugin/\r
+ * Dual licensed under the MIT and GPL licenses:\r
+ *   http://www.opensource.org/licenses/mit-license.php\r
+ *   http://www.gnu.org/licenses/gpl.html\r
+ *\r
+ * Based on 'javascript i18n that almost doesn't suck' by markos\r
+ * http://markos.gaivo.net/blog/?p=100\r
+ *\r
+ * Revision: $Id$\r
+ * Version: 1.0.0  Feb-10-2008\r
+ */\r
+ (function($) {\r
+/**\r
+ * i18n provides a mechanism for translating strings using a jscript dictionary.\r
+ *\r
+ */\r
+\r
+\r
+/*\r
+ * i18n property list\r
+ */\r
+$.i18n = {\r
+\r
+/**\r
+ * setDictionary()\r
+ * Initialise the dictionary and translate nodes\r
+ *\r
+ * @param property_list i18n_dict : The dictionary to use for translation\r
+ */\r
+       setDictionary: function(i18n_dict) {\r
+               i18n_dict = i18n_dict;\r
+       },\r
+\r
+/**\r
+ * _()\r
+ * The actual translation function. Looks the given string up in the\r
+ * dictionary and returns the translation if one exists. If a translation\r
+ * is not found, returns the original word\r
+ *\r
+ * @param string str : The string to translate\r
+ * @param property_list params : params for using printf() on the string\r
+ * @return string : Translated word\r
+ *\r
+ */\r
+       _: function (str, params) {\r
+               var transl = str;\r
+               if (i18n_dict&& i18n_dict[str]) {\r
+                       transl = i18n_dict[str];\r
+               }\r
+               return this.printf(transl, params);\r
+       },\r
+\r
+/**\r
+ * toEntity()\r
+ * Change non-ASCII characters to entity representation\r
+ *\r
+ * @param string str : The string to transform\r
+ * @return string result : Original string with non-ASCII content converted to entities\r
+ *\r
+ */\r
+       toEntity: function (str) {\r
+               var result = '';\r
+               for (var i=0;i<str.length; i++) {\r
+                       if (str.charCodeAt(i) > 128)\r
+                               result += "&#"+str.charCodeAt(i)+";";\r
+                       else\r
+                               result += str.charAt(i);\r
+               }\r
+               return result;\r
+       },\r
+\r
+/**\r
+ * stripStr()\r
+ *\r
+ * @param string str : The string to strip\r
+ * @return string result : Stripped string\r
+ *\r
+ */\r
+       stripStr: function(str) {\r
+               return str.replace(/^\s*/, "").replace(/\s*$/, "");\r
+       },\r
+\r
+/**\r
+ * stripStrML()\r
+ *\r
+ * @param string str : The multi-line string to strip\r
+ * @return string result : Stripped string\r
+ *\r
+ */\r
+       stripStrML: function(str) {\r
+               // Split because m flag doesn't exist before JS1.5 and we need to\r
+               // strip newlines anyway\r
+               var parts = str.split('\n');\r
+               for (var i=0; i<parts.length; i++)\r
+                       parts[i] = stripStr(parts[i]);\r
+\r
+               // Don't join with empty strings, because it "concats" words\r
+               // And strip again\r
+               return stripStr(parts.join(" "));\r
+       },\r
+\r
+/*\r
+ * printf()\r
+ * C-printf like function, which substitutes %s with parameters\r
+ * given in list. %%s is used to escape %s.\r
+ *\r
+ * Doesn't work in IE5.0 (splice)\r
+ *\r
+ * @param string S : string to perform printf on.\r
+ * @param string L : Array of arguments for printf()\r
+ */\r
+       printf: function(S, L) {\r
+               if (!L) return S;\r
+\r
+               var nS = "";\r
+               var tS = S.split("%s");\r
+\r
+               for(var i=0; i<L.length; i++) {\r
+                       if (tS[i].lastIndexOf('%') == tS[i].length-1 && i != L.length-1)\r
+                               tS[i] += "s"+tS.splice(i+1,1)[0];\r
+                       nS += tS[i] + L[i];\r
+               }\r
+               return nS + tS[tS.length-1];\r
+       }\r
+\r
+};\r
+\r
+\r
+})(jQuery);\r
+\r
+\r
+//var i18nLang;\r
+var i18nZh = {\r
+       'insufficient privilege':'??????????',\r
+       'cannot pick own answer as best':'??????????????',\r
+       'anonymous users cannot select favorite questions':'?????????????',\r
+       'please login':'??????',\r
+       'anonymous users cannot vote':'????????',\r
+       '>15 points requried to upvote':'??+15?????????',\r
+       '>100 points required to downvote':'??+100?????????',\r
+       'please see': '??',\r
+       'cannot vote for own posts':'??????????',\r
+       'daily vote cap exhausted':'????????????????',\r
+       'cannot revoke old vote':'??????????????',\r
+       'please confirm offensive':"??????????????????????",\r
+       'anonymous users cannot flag offensive posts':'???????????',\r
+       'cannot flag message as offensive twice':'???????',\r
+       'flag offensive cap exhausted':'?????????????5?\91??\92???',\r
+       'need >15 points to report spam':"??+15??????\91???\92?",\r
+       'confirm delete':"?????/????????",\r
+       'anonymous users cannot delete/undelete':"???????????????",\r
+       'post recovered':"?????????????",\r
+       'post deleted':"????????????",\r
+       'add comment':'????',\r
+       'community karma points':'????',\r
+       'to comment, need':'????',\r
+       'delete this comment':'?????',\r
+       'hide comments':"????",\r
+       'add a comment':"????",\r
+       'comments':"??",\r
+       'confirm delete comment':"?????????",\r
+       'characters':'??',\r
+       'can write':'???',\r
+       'click to close':'???????',\r
+       'loading...':'???...',\r
+       'tags cannot be empty':'???????',\r
+       'tablimits info':"??5????????????20????",\r
+       'content cannot be empty':'???????',\r
+       'content minchars': '????? {0} ???',\r
+       'please enter title':'??????',\r
+       'title minchars':"????? {0} ???",\r
+       'delete':'??',\r
+       'undelete':     '??',\r
+       'bold':'??',\r
+       'italic':'??',\r
+       'link':'???',\r
+       'quote':'??',\r
+       'preformatted text':'??',\r
+       'image':'??',\r
+       'numbered list':'??????',\r
+       'bulleted list':'??????',\r
+       'heading':'??',\r
+       'horizontal bar':'???',\r
+       'undo':'??',\r
+       'redo':'??',\r
+       'enter image url':'<b>??????</b></p><p>???<br />http://www.example.com/image.jpg   \"????\"',\r
+       'enter url':'<b>??Web??</b></p><p>???<br />http://www.cnprog.com/   \"????\"</p>"',\r
+       'upload image':'?????????'\r
+};\r
+\r
+var i18nEn = {\r
+       'need >15 points to report spam':'need >15 points to report spam ',\r
+    '>15 points requried to upvote':'>15 points required to upvote ',\r
+       'tags cannot be empty':'please enter at least one tag',\r
+       'anonymous users cannot vote':'sorry, anonymous users cannot vote ',\r
+       'anonymous users cannot select favorite questions':'sorry, anonymous users cannot select favorite questions ',\r
+       'to comment, need': '(to comment other people\'s posts, karma ',\r
+       'please see':'please see ',\r
+       'community karma points':' or more is necessary) - ',\r
+       'upload image':'Upload image:',\r
+       'enter image url':'enter URL of the image, e.g. http://www.example.com/image.jpg \"image title\"',\r
+       'enter url':'enter Web address, e.g. http://www.example.com \"page title\"',\r
+       'daily vote cap exhausted':'sorry, you\'ve used up todays vote cap',\r
+       'cannot pick own answer as best':'sorry, you cannot accept your own answer',\r
+       'cannot revoke old vote':'sorry, older votes cannot be revoked',\r
+       'please confirm offensive':'are you sure this post is offensive, contains spam, advertising, malicious remarks, etc.?',\r
+       'flag offensive cap exhausted':'sorry, you\'ve used up todays cap of flagging offensive messages ',\r
+       'confirm delete':'are you sure you want to delete this?',\r
+       'anonymous users cannot delete/undelete':'sorry, anonymous users cannot delete or undelete posts',\r
+       'post recovered':'your post is now restored!',\r
+       'post deleted':'your post has been deleted',\r
+       'confirm delete comment':'do you really want to delete this comment?',\r
+       'can write':'have ',\r
+       'tablimits info':'up to 5 tags, no more than 20 characters each',\r
+       'content minchars': 'please enter more than {0} characters',\r
+       'title minchars':"please enter at least {0} characters",\r
+       'characters':'characters left',\r
+    'cannot vote for own posts':'sorry, you cannot vote for your own posts',\r
+    'cannot flag message as offensive twice':'cannot flag message as offensive twice ',\r
+       '>100 points required to downvote':'>100 points required to downvote '\r
+};\r
+\r
+var i18nEs = {\r
+       'insufficient privilege':'privilegio insuficiente',\r
+       'cannot pick own answer as best':'no puede escoger su propia respuesta como la mejor',\r
+       'anonymous users cannot select favorite questions':'usuarios anonimos no pueden seleccionar',\r
+       'please login':'por favor inicie sesión',\r
+       'anonymous users cannot vote':'usuarios anónimos no pueden votar',\r
+       '>15 points requried to upvote': '>15 puntos requeridos para votar positivamente',\r
+       '>100 points required to downvote':'>100 puntos requeridos para votar negativamente',\r
+       'please see': 'por favor vea',\r
+       'cannot vote for own posts':'no se puede votar por sus propias publicaciones',\r
+       'daily vote cap exhausted':'cuota de votos diarios excedida',\r
+       'cannot revoke old vote':'no puede revocar un voto viejo',\r
+       'please confirm offensive':"por favor confirme ofensiva",\r
+       'anonymous users cannot flag offensive posts':'usuarios anónimos no pueden marcar publicaciones como ofensivas',\r
+       'cannot flag message as offensive twice':'no puede marcar mensaje como ofensivo dos veces',\r
+       'flag offensive cap exhausted':'cuota para marcar ofensivas ha sido excedida',\r
+       'need >15 points to report spam':"necesita >15 puntos para reportar spam",\r
+       'confirm delete':"¿Está seguro que desea borrar esto?",\r
+       'anonymous users cannot delete/undelete':"usuarios anónimos no pueden borrar o recuperar publicaciones",\r
+       'post recovered':"publicación recuperada",\r
+       'post deleted':"publicación borrada?",\r
+       'add comment':'agregar comentario',\r
+       'community karma points':'reputación comunitaria',\r
+       'to comment, need':'para comentar, necesita reputación',\r
+       'delete this comment':'borrar este comentario',\r
+       'hide comments':"ocultar comentarios",\r
+       'add a comment':"agregar comentarios",\r
+       'comments':"comentarios",\r
+       'confirm delete comment':"¿Realmente desea borrar este comentario?",\r
+       'characters':'caracteres faltantes',\r
+       'can write':'tiene ',\r
+       'click to close':'haga click para cerrar',\r
+       'loading...':'cargando...',\r
+       'tags cannot be empty':'las etiquetas no pueden estar vacías',\r
+       'tablimits info':"hasta 5 etiquetas de no mas de 20 caracteres cada una",\r
+       'content cannot be empty':'el contenido no puede estar vacío',\r
+       'content minchars': 'por favor introduzca mas de {0} caracteres',\r
+       'please enter title':'por favor ingrese un título',\r
+       'title minchars':"por favor introduzca al menos {0} caracteres",\r
+       'delete':'borrar',\r
+       'undelete':     'recuperar',\r
+       'bold': 'negrita',\r
+       'italic':'cursiva',\r
+       'link':'enlace',\r
+       'quote':'citar',\r
+       'preformatted text':'texto preformateado',\r
+       'image':'imagen',\r
+       'numbered list':'lista numerada',\r
+       'bulleted list':'lista no numerada',\r
+       'heading':'??',\r
+       'horizontal bar':'barra horizontal',\r
+       'undo':'deshacer',\r
+       'redo':'rehacer',\r
+       'enter image url':'introduzca la URL de la imagen, por ejemplo?<br />http://www.example.com/image.jpg   \"titulo de imagen\"',\r
+       'enter url':'introduzca direcciones web, ejemplo?<br />http://www.cnprog.com/   \"titulo del enlace\"</p>"',\r
+       'upload image':'cargar imagen?',\r
+       'questions/' : 'preguntas/',\r
+       'vote/' : 'votar/'\r
+};\r
+\r
+var i18n = {\r
+       'en':i18nEn,\r
+       'zh_CN':i18nZh,\r
+       'es':i18nEs\r
+};\r
+\r
+var i18n_dict = i18n[i18nLang];\r
+\r
+/*\r
+       jQuery TextAreaResizer plugin\r
+       Created on 17th January 2008 by Ryan O'Dell\r
+       Version 1.0.4\r
+*/(function($){var textarea,staticOffset;var iLastMousePos=0;var iMin=32;var grip;$.fn.TextAreaResizer=function(){return this.each(function(){textarea=$(this).addClass('processed'),staticOffset=null;$(this).wrap('<div class="resizable-textarea"><span></span></div>').parent().append($('<div class="grippie"></div>').bind("mousedown",{el:this},startDrag));var grippie=$('div.grippie',$(this).parent())[0];grippie.style.marginRight=(grippie.offsetWidth-$(this)[0].offsetWidth)+'px'})};function startDrag(e){textarea=$(e.data.el);textarea.blur();iLastMousePos=mousePosition(e).y;staticOffset=textarea.height()-iLastMousePos;textarea.css('opacity',0.25);$(document).mousemove(performDrag).mouseup(endDrag);return false}function performDrag(e){var iThisMousePos=mousePosition(e).y;var iMousePos=staticOffset+iThisMousePos;if(iLastMousePos>=(iThisMousePos)){iMousePos-=5}iLastMousePos=iThisMousePos;iMousePos=Math.max(iMin,iMousePos);textarea.height(iMousePos+'px');if(iMousePos<iMin){endDrag(e)}return false}function endDrag(e){$(document).unbind('mousemove',performDrag).unbind('mouseup',endDrag);textarea.css('opacity',1);textarea.focus();textarea=null;staticOffset=null;iLastMousePos=0}function mousePosition(e){return{x:e.clientX+document.documentElement.scrollLeft,y:e.clientY+document.documentElement.scrollTop}}})(jQuery);\r
+/*\r
+ * Autocomplete - jQuery plugin 1.0.3\r
+ *\r
+ * Copyright (c) 2007 Dylan Verheul, Dan G. Switzer, Anjesh Tuladhar, Jörn Zaefferer\r
+ *\r
+ * Dual licensed under the MIT and GPL licenses:\r
+ *   http://www.opensource.org/licenses/mit-license.php\r
+ *   http://www.gnu.org/licenses/gpl.html\r
+ *\r
+ */\r
+(function(a){a.fn.extend({autocomplete:function(b,c){var d=typeof b=="string";c=a.extend({},a.Autocompleter.defaults,{url:d?b:null,data:d?null:b,delay:d?a.Autocompleter.defaults.delay:10,max:c&&!c.scroll?10:150},c);c.highlight=c.highlight||function(e){return e};c.formatMatch=c.formatMatch||c.formatItem;return this.each(function(){new a.Autocompleter(this,c)})},result:function(b){return this.bind("result",b)},search:function(b){return this.trigger("search",[b])},flushCache:function(){return this.trigger("flushCache")},setOptions:function(b){return this.trigger("setOptions",[b])},unautocomplete:function(){return this.trigger("unautocomplete")}});a.Autocompleter=function(l,g){var c={UP:38,DOWN:40,DEL:46,TAB:9,RETURN:13,ESC:27,COMMA:188,PAGEUP:33,PAGEDOWN:34,BACKSPACE:8};var b=a(l).attr("autocomplete","off").addClass(g.inputClass);var j;var p="";var m=a.Autocompleter.Cache(g);var e=0;var u;var x={mouseDownOnSelect:false};var r=a.Autocompleter.Select(g,l,d,x);var w;a.browser.opera&&a(l.form).bind("submit.autocomplete",function(){if(w){w=false;return false}});b.bind((a.browser.opera?"keypress":"keydown")+".autocomplete",function(y){u=y.keyCode;switch(y.keyCode){case c.UP:y.preventDefault();if(r.visible()){r.prev()}else{t(0,true)}break;case c.DOWN:y.preventDefault();if(r.visible()){r.next()}else{t(0,true)}break;case c.PAGEUP:y.preventDefault();if(r.visible()){r.pageUp()}else{t(0,true)}break;case c.PAGEDOWN:y.preventDefault();if(r.visible()){r.pageDown()}else{t(0,true)}break;case g.multiple&&a.trim(g.multipleSeparator)==","&&c.COMMA:case c.TAB:case c.RETURN:if(d()){y.preventDefault();w=true;return false}break;case c.ESC:r.hide();break;default:clearTimeout(j);j=setTimeout(t,g.delay);break}}).focus(function(){e++}).blur(function(){e=0;if(!x.mouseDownOnSelect){s()}}).click(function(){if(e++>1&&!r.visible()){t(0,true)}}).bind("search",function(){var y=(arguments.length>1)?arguments[1]:null;function z(D,C){var A;if(C&&C.length){for(var B=0;B<C.length;B++){if(C[B].result.toLowerCase()==D.toLowerCase()){A=C[B];break}}}if(typeof y=="function"){y(A)}else{b.trigger("result",A&&[A.data,A.value])}}a.each(h(b.val()),function(A,B){f(B,z,z)})}).bind("flushCache",function(){m.flush()}).bind("setOptions",function(){a.extend(g,arguments[1]);if("data" in arguments[1]){m.populate()}}).bind("unautocomplete",function(){r.unbind();b.unbind();a(l.form).unbind(".autocomplete")});function d(){var z=r.selected();if(!z){return false}var y=z.result;p=y;if(g.multiple){var A=h(b.val());if(A.length>1){y=A.slice(0,A.length-1).join(g.multipleSeparator)+g.multipleSeparator+y}y+=g.multipleSeparator}b.val(y);v();b.trigger("result",[z.data,z.value]);return true}function t(A,z){if(u==c.DEL){r.hide();return}var y=b.val();if(!z&&y==p){return}p=y;y=i(y);if(y.length>=g.minChars){b.addClass(g.loadingClass);if(!g.matchCase){y=y.toLowerCase()}f(y,k,v)}else{n();r.hide()}}function h(z){if(!z){return[""]}var A=z.split(g.multipleSeparator);var y=[];a.each(A,function(B,C){if(a.trim(C)){y[B]=a.trim(C)}});return y}function i(y){if(!g.multiple){return y}var z=h(y);return z[z.length-1]}function q(y,z){if(g.autoFill&&(i(b.val()).toLowerCase()==y.toLowerCase())&&u!=c.BACKSPACE){b.val(b.val()+z.substring(i(p).length));a.Autocompleter.Selection(l,p.length,p.length+z.length)}}function s(){clearTimeout(j);j=setTimeout(v,200)}function v(){var y=r.visible();r.hide();clearTimeout(j);n();if(g.mustMatch){b.search(function(z){if(!z){if(g.multiple){var A=h(b.val()).slice(0,-1);b.val(A.join(g.multipleSeparator)+(A.length?g.multipleSeparator:""))}else{b.val("")}}})}if(y){a.Autocompleter.Selection(l,l.value.length,l.value.length)}}function k(z,y){if(y&&y.length&&e){n();r.display(y,z);q(z,y[0].value);r.show()}else{v()}}function f(z,B,y){if(!g.matchCase){z=z.toLowerCase()}var A=m.load(z);if(A&&A.length){B(z,A)}else{if((typeof g.url=="string")&&(g.url.length>0)){var C={timestamp:+new Date()};a.each(g.extraParams,function(D,E){C[D]=typeof E=="function"?E():E});a.ajax({mode:"abort",port:"autocomplete"+l.name,dataType:g.dataType,url:g.url,data:a.extend({q:i(z),limit:g.max},C),success:function(E){var D=g.parse&&g.parse(E)||o(E);m.add(z,D);B(z,D)}})}else{r.emptyList();y(z)}}}function o(B){var y=[];var A=B.split("\n");for(var z=0;z<A.length;z++){var C=a.trim(A[z]);if(C){C=C.split("|");y[y.length]={data:C,value:C[0],result:g.formatResult&&g.formatResult(C,C[0])||C[0]}}}return y}function n(){b.removeClass(g.loadingClass)}};a.Autocompleter.defaults={inputClass:"ac_input",resultsClass:"ac_results",loadingClass:"ac_loading",minChars:1,delay:400,matchCase:false,matchSubset:true,matchContains:false,cacheLength:10,max:100,mustMatch:false,extraParams:{},selectFirst:true,formatItem:function(b){return b[0]},formatMatch:null,autoFill:false,width:0,multiple:false,multipleSeparator:", ",highlight:function(c,b){return c.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)("+b.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi,"\\$1")+")(?![^<>]*>)(?![^&;]+;)","gi"),"<strong>$1</strong>")},scroll:true,scrollHeight:180};a.Autocompleter.Cache=function(c){var f={};var d=0;function h(l,k){if(!c.matchCase){l=l.toLowerCase()}var j=l.indexOf(k);if(j==-1){return false}return j==0||c.matchContains}function g(j,i){if(d>c.cacheLength){b()}if(!f[j]){d++}f[j]=i}function e(){if(!c.data){return false}var k={},j=0;if(!c.url){c.cacheLength=1}k[""]=[];for(var m=0,l=c.data.length;m<l;m++){var p=c.data[m];p=(typeof p=="string")?[p]:p;var o=c.formatMatch(p,m+1,c.data.length);if(o===false){continue}var n=o.charAt(0).toLowerCase();if(!k[n]){k[n]=[]}var q={value:o,data:p,result:c.formatResult&&c.formatResult(p)||o};k[n].push(q);if(j++<c.max){k[""].push(q)}}a.each(k,function(r,s){c.cacheLength++;g(r,s)})}setTimeout(e,25);function b(){f={};d=0}return{flush:b,add:g,populate:e,load:function(n){if(!c.cacheLength||!d){return null}if(!c.url&&c.matchContains){var m=[];for(var j in f){if(j.length>0){var o=f[j];a.each(o,function(p,k){if(h(k.value,n)){m.push(k)}})}}return m}else{if(f[n]){return f[n]}else{if(c.matchSubset){for(var l=n.length-1;l>=c.minChars;l--){var o=f[n.substr(0,l)];if(o){var m=[];a.each(o,function(p,k){if(h(k.value,n)){m[m.length]=k}});return m}}}}}return null}}};a.Autocompleter.Select=function(e,j,l,p){var i={ACTIVE:"ac_over"};var k,f=-1,r,m="",s=true,c,o;function n(){if(!s){return}c=a("<div/>").hide().addClass(e.resultsClass).css("position","absolute").appendTo(document.body);o=a("<ul/>").appendTo(c).mouseover(function(t){if(q(t).nodeName&&q(t).nodeName.toUpperCase()=="LI"){f=a("li",o).removeClass(i.ACTIVE).index(q(t));a(q(t)).addClass(i.ACTIVE)}}).click(function(t){a(q(t)).addClass(i.ACTIVE);l();j.focus();return false}).mousedown(function(){p.mouseDownOnSelect=true}).mouseup(function(){p.mouseDownOnSelect=false});if(e.width>0){c.css("width",e.width)}s=false}function q(u){var t=u.target;while(t&&t.tagName!="LI"){t=t.parentNode}if(!t){return[]}return t}function h(t){k.slice(f,f+1).removeClass(i.ACTIVE);g(t);var v=k.slice(f,f+1).addClass(i.ACTIVE);if(e.scroll){var u=0;k.slice(0,f).each(function(){u+=this.offsetHeight});if((u+v[0].offsetHeight-o.scrollTop())>o[0].clientHeight){o.scrollTop(u+v[0].offsetHeight-o.innerHeight())}else{if(u<o.scrollTop()){o.scrollTop(u)}}}}function g(t){f+=t;if(f<0){f=k.size()-1}else{if(f>=k.size()){f=0}}}function b(t){return e.max&&e.max<t?e.max:t}function d(){o.empty();var u=b(r.length);for(var v=0;v<u;v++){if(!r[v]){continue}var w=e.formatItem(r[v].data,v+1,u,r[v].value,m);if(w===false){continue}var t=a("<li/>").html(e.highlight(w,m)).addClass(v%2==0?"ac_even":"ac_odd").appendTo(o)[0];a.data(t,"ac_data",r[v])}k=o.find("li");if(e.selectFirst){k.slice(0,1).addClass(i.ACTIVE);f=0}if(a.fn.bgiframe){o.bgiframe()}}return{display:function(u,t){n();r=u;m=t;d()},next:function(){h(1)},prev:function(){h(-1)},pageUp:function(){if(f!=0&&f-8<0){h(-f)}else{h(-8)}},pageDown:function(){if(f!=k.size()-1&&f+8>k.size()){h(k.size()-1-f)}else{h(8)}},hide:function(){c&&c.hide();k&&k.removeClass(i.ACTIVE);f=-1},visible:function(){return c&&c.is(":visible")},current:function(){return this.visible()&&(k.filter("."+i.ACTIVE)[0]||e.selectFirst&&k[0])},show:function(){var v=a(j).offset();c.css({width:typeof e.width=="string"||e.width>0?e.width:a(j).width(),top:v.top+j.offsetHeight,left:v.left}).show();if(e.scroll){o.scrollTop(0);o.css({maxHeight:e.scrollHeight,overflow:"auto"});if(a.browser.msie&&typeof document.body.style.maxHeight==="undefined"){var t=0;k.each(function(){t+=this.offsetHeight});var u=t>e.scrollHeight;o.css("height",u?e.scrollHeight:t);if(!u){k.width(o.width()-parseInt(k.css("padding-left"))-parseInt(k.css("padding-right")))}}}},selected:function(){var t=k&&k.filter("."+i.ACTIVE).removeClass(i.ACTIVE);return t&&t.length&&a.data(t[0],"ac_data")},emptyList:function(){o&&o.empty()},unbind:function(){c&&c.remove()}}};a.Autocompleter.Selection=function(d,e,c){if(d.setSelectionRange){d.setSelectionRange(e,c)}else{if(d.createTextRange){var b=d.createTextRange();b.collapse(true);b.moveStart("character",e);b.moveEnd("character",c);b.select()}else{if(d.selectionStart){d.selectionStart=e;d.selectionEnd=c}}}d.focus()}})(jQuery);\r
+\r
+var notify = function() {\r
+    var visible = false;\r
+    return {\r
+        show: function(html) {\r
+            if (html) {\r
+                $("body").css("margin-top", "2.2em");\r
+                $(".notify span").html(html);\r
+            }\r
+            $(".notify").fadeIn("slow");\r
+            visible = true;\r
+        },\r
+        close: function(doPostback) {\r
+            $(".notify").fadeOut("fast");\r
+            $("body").css("margin-top", "0");\r
+            visible = false;\r
+        },\r
+        isVisible: function() { return visible; }\r
+    };\r
+} ();\r
+\r
+/*\r
+ * jQuery outside events - v1.1 - 3/16/2010\r
+ * http://benalman.com/projects/jquery-outside-events-plugin/\r
+ *\r
+ * Copyright (c) 2010 "Cowboy" Ben Alman\r
+ * Dual licensed under the MIT and GPL licenses.\r
+ * http://benalman.com/about/license/\r
+ */\r
+(function($,c,b){$.map("click dblclick mousemove mousedown mouseup mouseover mouseout change select submit keydown keypress keyup".split(" "),function(d){a(d)});a("focusin","focus"+b);a("focusout","blur"+b);$.addOutsideEvent=a;function a(g,e){e=e||g+b;var d=$(),h=g+"."+e+"-special-event";$.event.special[e]={setup:function(){d=d.add(this);if(d.length===1){$(c).bind(h,f)}},teardown:function(){d=d.not(this);if(d.length===0){$(c).unbind(h)}},add:function(i){var j=i.handler;i.handler=function(l,k){l.target=k;j.apply(this,arguments)}}};function f(i){$(d).each(function(){var j=$(this);if(this!==i.target&&!j.has(i.target).length){j.triggerHandler(e,[i.target])}})}}})(jQuery,document,"outside");\r
+\r
+$(document).ready( function(){\r
+    pickedTags().init();\r
+\r
+    $('input#bnewaccount').click(function() {\r
+        $('#bnewaccount').disabled=true;\r
+    });\r
+});\r
+\r
+function yourWorkWillBeLost(e) {\r
+    if(browserTester('chrome')) {\r
+        return "Are you sure you want to leave?  Your work will be lost.";\r
+    } else if(browserTester('safari')) {\r
+        return "Are you sure you want to leave?  Your work will be lost.";\r
+    } else {\r
+        if(!e) e = window.event;\r
+        e.cancelBubble = true;\r
+        e.returnValue = 'If you leave, your work will be lost.';\r
+\r
+        if (e.stopPropagation) {\r
+            e.stopPropagation();\r
+            e.preventDefault();\r
+        }\r
+        return e;\r
+    }\r
+}\r
+\r
+function browserTester(browserString) {\r
+    return navigator.userAgent.toLowerCase().indexOf(browserString) > -1;\r
+}\r
+\r
+// Add missing IE functionality\r
+if (!window.addEventListener) {\r
+    if (window.attachEvent) {\r
+        window.addEventListener = function (type, listener, useCapture) {\r
+            window.attachEvent('on' + type, listener);\r
+        };\r
+        window.removeEventListener = function (type, listener, useCapture) {\r
+            window.detachEvent('on' + type, listener);\r
+        };\r
+    } else {\r
+        window.addEventListener = function (type, listener, useCapture) {\r
+            window['on' + type] = listener;\r
+        };\r
+        window.removeEventListener = function (type, listener, useCapture) {\r
+            window['on' + type] = null;\r
+        };\r
+    }\r
+}\r
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/osqa.main.min.js b/forum/modules/template_loader.py/forum/skins/default/media/js/osqa.main.min.js
new file mode 100644 (file)
index 0000000..4422926
--- /dev/null
@@ -0,0 +1 @@
+var response_commands={update_post_score:function(a,d,b){var c=$("#"+a+"-"+d+"-score");c.html(parseInt(c.html())+b)},update_user_post_vote:function(c,e,b){var a=$("#"+c+"-"+e+"-upvote");var d=$("#"+c+"-"+e+"-downvote");a.removeClass("on");d.removeClass("on");if(b=="up"){a.addClass("on")}else{if(b=="down"){d.addClass("on")}}},update_favorite_count:function(b){var c=$("#favorite-count");var a=parseInt(c.html());if(isNaN(a)){a=0}a+=b;if(a==0){a=""}c.html(a)},update_favorite_mark:function(a){if(a=="on"){$("#favorite-mark").addClass("on")}else{$("#favorite-mark").removeClass("on")}},mark_accepted:function(b){$(".accepted-answer").removeClass("accepted-answer");$(".accept-answer.on").removeClass("on");var a=$("#answer-container-"+b);a.addClass("accepted-answer");a.find(".accept-answer").addClass("on")},unmark_accepted:function(b){var a=$("#answer-container-"+b);a.removeClass("accepted-answer");a.find(".accept-answer").removeClass("on")},update_comment_score:function(d,b){var c=$("#comment-"+d+"-score");var a=parseInt(c.html());if(isNaN(a)){a=0}a+=b;if(a==0){a=""}c.html(a)},update_likes_comment_mark:function(c,a){var b=$("#comment-"+c+"-like");if(a=="on"){b.addClass("on")}else{b.removeClass("on")}},remove_comment:function(b){var a=$("#comment-"+b);a.css("background","red");a.fadeOut("slow",function(){a.remove()})},insert_comment:function(g,c,a,f,e,h,b){var i=$("#comments-container-"+g+"-"+c);var d=$("#new-comment-skeleton-"+g+"-"+c).html().toString();d=d.replace(new RegExp("%ID%","g"),a).replace(new RegExp("%COMMENT%","g"),f).replace(new RegExp("%USERNAME%","g"),e).replace(new RegExp("%PROFILE_URL%","g"),h).replace(new RegExp("%DELETE_URL%","g"),b);i.append(d);$("#comment-"+a).slideDown("slow")},update_comment:function(b,a){var c=$("#comment-"+b);c.find(".comment-text").html(a);c.slideDown("slow")},mark_deleted:function(b,a){if(b=="answer"){var d=$("#answer-container-"+a);d.addClass("deleted")}else{var c=$("#question-table");c.addClass("deleted")}},set_subscription_button:function(a){$(".subscription_switch").html(a)},set_subscription_status:function(a){$(".subscription-status").html(a)}};function show_message(a,b){var c=$('<div class="vote-notification"><h3>'+b+"</h3>(click to close)</div>");c.click(function(d){$(".vote-notification").fadeOut("fast",function(){$(this).remove()})});a.parent().append(c);c.fadeIn("fast")}function process_ajax_response(b,a){if(!b.success&&b.error_message!=undefined){show_message(a,b.error_message)}else{if(typeof b.commands!=undefined){for(var c in b.commands){response_commands[c].apply(null,b.commands[c])}if(b.message!=undefined){show_message(a,b.message)}}}}$(function(){$("a.ajax-command").live("click",function(){var a=$(this);$.getJSON(a.attr("href"),function(b){process_ajax_response(b,a)});return false});$("div.comment-form-container").each(function(){var l=$(this);var o=l.find("form");var g=l.find("textarea");var a=l.find('input[type="submit"]');var e=$(".comment-chars-left");var b=l.find(".comments-char-left-count");var m=l.parent().find(".comment-tools");var n=m.find(".add-comment-link");var f=l.parent().find(".comments-container");var k=parseInt(b.html());var h=false;function i(){g.val("");b.html(k);e.removeClass("warn");h=false}i();function d(){var q=g.val().length;var p=true;if(q<k){if(q<k*0.75){e.removeClass("warn")}else{e.addClass("warn")}}else{p=false}b.html(k-q);return p}function c(){l.slideDown("slow");n.fadeOut("slow")}function j(){l.slideUp("slow");n.fadeIn("slow")}n.click(function(){i();c();return false});m.find(".show-all-comments-link").click(function(){f.find(".not_top_scorer").slideDown("slow");$(this).fadeOut("slow");m.find(".comments-showing").fadeOut("slow");return false});$("#"+f.attr("id")+" .comment-edit").live("click",function(){var q=$(this);var r=/comment-(\d+)-edit/.exec(q.attr("id"))[1];var s=q.parents(".comment");var p=s.find(".comment-text").text().trim();h=r;g.val(p);d();s.slideUp("slow");c();return false});g.keyup(d);a.click(function(){if(g.val().length>k){show_message(a,"Your comment exceeds the max number of characters allowed.")}else{var p={comment:g.val()};if(h){p.id=h}$.post(o.attr("action"),p,function(q){process_ajax_response(q,a);i()},"json")}j();return false})})});function pickedTags(){var a=function(j,k,i,l){var h=scriptUrl;if(i=="add"){h+=$.i18n._("mark-tag/");if(k=="good"){h+=$.i18n._("interesting/")}else{h+=$.i18n._("ignored/")}}else{h+=$.i18n._("unmark-tag/")}h=h+j+"/";var g={type:"POST",url:h};if(l!==false){g.success=l}$.ajax(g)};var f=function(k,h,i,g){var j=function(){k[h].remove();delete k[h]};if(g){a(h,i,"remove",j)}else{j()}};var b=function(k,h,i,j,g){k.unbind("mouseover").bind("mouseover",function(){$(this).attr("src",mediaUrl("media/images/close-small-hover.png"))});k.unbind("mouseout").bind("mouseout",function(){$(this).attr("src",mediaUrl("media/images/close-small-dark.png"))});k.click(function(){f(h,i,j,g)})};var d=function(k,j){var i=$.trim($(k).prev().attr("value"));var g=interestingTags;var l=ignoredTags;var h;if(j=="bad"){g=ignoredTags;l=interestingTags;h=$("div .tags.ignored")}else{if(j!="good"){return}else{h=$("div .tags.interesting")}}if(i in l){f(l,i,j,false)}if(!(i in g)){a(i,j,"add",function(){var n=$("<span></span>");n.addClass("deletable-tag");var m=$("<a></a>");m.attr("rel","tag");m.attr("href",scriptUrl+$.i18n._("tags/")+i);m.html(i);var o=$("<img></img>");o.addClass("delete-icon");o.attr("src",mediaUrl("/media/images/close-small-dark.png"));b(o,g,i,j,true);n.append(m);n.append(o);h.append(n);g[i]=n})}};var c=function(){var g="interesting-tag-";var j="ignored-tag-";var i=RegExp("^"+g);var h=RegExp("^"+j);interestingTags={};ignoredTags={};$(".deletable-tag").each(function(l,n){var k=$(n).attr("id");var o,m;if(i.test(k)){o=k.replace(g,"");m=interestingTags;reason="good"}else{if(h.test(k)){o=k.replace(j,"");m=ignoredTags;reason="bad"}else{return}}m[o]=$(n);b($(n).find("img"),m,o,reason,true)})};var e=function(){$("#hideIgnoredTagsCb").unbind("click").click(function(){$.ajax({type:"POST",dataType:"json",cache:false,url:scriptUrl+$.i18n._("command/"),data:{command:"toggle-ignored-questions"}})})};return{init:function(){c();e();$("#interestingTagInput, #ignoredTagInput").autocomplete(tags,{minChars:1,matchContains:true,max:20,multiple:true,multipleSeparator:" ",formatItem:function(j,h,g){return j.n+" ("+j.c+")"},formatResult:function(j,h,g){return j.n}});$("#interestingTagAdd").click(function(){d(this,"good")});$("#ignoredTagAdd").click(function(){d(this,"bad")})}}}$(document).ready(function(){if(window.tags!=undefined){pickedTags().init()}});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(m){var j=null;var l=new RegExp("");for(var n=0;n<Hilite.search_engines.length;n++){var k=Hilite.search_engines[n];l.compile("^http://(www\\.)?"+k[0],"i");var h=m.match(l);if(h){var i;if(isNaN(k[1])){i=Hilite.decodeReferrerQS(m,k[1])}else{i=h[k[1]+1]}if(i){i=decodeURIComponent(i);if(k.length>2&&k[2]){i=decodeURIComponent(i)}i=i.replace(/\'|"/g,"");i=i.split(/[\s,\+\.]+/);return i}break}}return null};Hilite.decodeReferrerQS=function(k,m){var h=k.indexOf("?");var n;if(h>=0){var i=new String(k.substring(h+1));h=0;n=0;while((h>=0)&&((n=i.indexOf("=",h))>=0)){var l,j;l=i.substring(h,n);h=i.indexOf("&",n)+1;if(l==m){if(h<=0){return i.substring(n+1)}else{return i.substring(n+1,h-1)}}else{if(h<=0){return null}}}}return null};Hilite.hiliteElement=function(i,j){if(!j||i.childNodes.length==0){return}var l=new Array();for(var g=0;g<j.length;g++){j[g]=j[g].toLowerCase();if(Hilite.exact){l.push("\\b"+j[g]+"\\b")}else{l.push(j[g])}}l=new RegExp(l.join("|"),"i");var h={};for(var g=0;g<j.length;g++){if(Hilite.style_name_suffix){h[j[g]]=Hilite.style_name+(g+1)}else{h[j[g]]=Hilite.style_name}}var k=function(a){var c=l.exec(a.data);if(c){var o=c[0];var d="";var e=a.splitText(c.index);var f=e.splitText(o.length);var b=a.ownerDocument.createElement("SPAN");a.parentNode.replaceChild(b,e);b.className=h[o.toLowerCase()];b.appendChild(e);return b}else{return a}};Hilite.walkElements(i.childNodes[0],1,k)};Hilite.hilite=function(){var d=Hilite.debug_referrer?Hilite.debug_referrer:document.referrer;var c=null;d=Hilite.decodeReferrer(d);if(d&&((Hilite.elementid&&(c=document.getElementById(Hilite.elementid)))||(c=document.body))){Hilite.hiliteElement(c,d)}};Hilite.walkElements=function(k,i,j){var h=/^(script|style|textarea)/i;var l=0;while(k&&i>0){l++;if(l>=Hilite.max_nodes){var g=function(){Hilite.walkElements(k,i,j)};setTimeout(g,50);return}if(k.nodeType==1){if(!h.test(k.tagName)&&k.childNodes.length>0){k=k.childNodes[0];i++;continue}}else{if(k.nodeType==3){k=j(k)}}if(k.nextSibling){k=k.nextSibling}else{while(i>0){k=k.parentNode;i--;if(k.nextSibling){k=k.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()}}}}var mediaUrl=function(a){return scriptUrl+"m/"+osqaSkin+"/"+a};(function(a){a.i18n={setDictionary:function(b){b=b},_:function(d,c){var b=d;if(i18n_dict&&i18n_dict[d]){b=i18n_dict[d]}return this.printf(b,c)},toEntity:function(d){var b="";for(var c=0;c<d.length;c++){if(d.charCodeAt(c)>128){b+="&#"+d.charCodeAt(c)+";"}else{b+=d.charAt(c)}}return b},stripStr:function(b){return b.replace(/^\s*/,"").replace(/\s*$/,"")},stripStrML:function(d){var c=d.split("\n");for(var b=0;b<c.length;b++){c[b]=stripStr(c[b])}return stripStr(c.join(" "))},printf:function(e,b){if(!b){return e}var d="";var f=e.split("%s");for(var c=0;c<b.length;c++){if(f[c].lastIndexOf("%")==f[c].length-1&&c!=b.length-1){f[c]+="s"+f.splice(c+1,1)[0]}d+=f[c]+b[c]}return d+f[f.length-1]}}})(jQuery);var i18nZh={"insufficient privilege":"??????????","cannot pick own answer as best":"??????????????","anonymous users cannot select favorite questions":"?????????????","please login":"??????","anonymous users cannot vote":"????????",">15 points requried to upvote":"??+15?????????",">100 points required to downvote":"??+100?????????","please see":"??","cannot vote for own posts":"??????????","daily vote cap exhausted":"????????????????","cannot revoke old vote":"??????????????","please confirm offensive":"??????????????????????","anonymous users cannot flag offensive posts":"???????????","cannot flag message as offensive twice":"???????","flag offensive cap exhausted":"?????????????5?�??�???","need >15 points to report spam":"??+15??????�???�?","confirm delete":"?????/????????","anonymous users cannot delete/undelete":"???????????????","post recovered":"?????????????","post deleted":"????????????","add comment":"????","community karma points":"????","to comment, need":"????","delete this comment":"?????","hide comments":"????","add a comment":"????",comments:"??","confirm delete comment":"?????????",characters:"??","can write":"???","click to close":"???????","loading...":"???...","tags cannot be empty":"???????","tablimits info":"??5????????????20????","content cannot be empty":"???????","content minchars":"????? {0} ???","please enter title":"??????","title minchars":"????? {0} ???","delete":"??",undelete:"??",bold:"??",italic:"??",link:"???",quote:"??","preformatted text":"??",image:"??","numbered list":"??????","bulleted list":"??????",heading:"??","horizontal bar":"???",undo:"??",redo:"??","enter image url":'<b>??????</b></p><p>???<br />http://www.example.com/image.jpg   "????"',"enter url":'<b>??Web??</b></p><p>???<br />http://www.cnprog.com/   "????"</p>"',"upload image":"?????????"};var i18nEn={"need >15 points to report spam":"need >15 points to report spam ",">15 points requried to upvote":">15 points required to upvote ","tags cannot be empty":"please enter at least one tag","anonymous users cannot vote":"sorry, anonymous users cannot vote ","anonymous users cannot select favorite questions":"sorry, anonymous users cannot select favorite questions ","to comment, need":"(to comment other people's posts, karma ","please see":"please see ","community karma points":" or more is necessary) - ","upload image":"Upload image:","enter image url":'enter URL of the image, e.g. http://www.example.com/image.jpg "image title"',"enter url":'enter Web address, e.g. http://www.example.com "page title"',"daily vote cap exhausted":"sorry, you've used up todays vote cap","cannot pick own answer as best":"sorry, you cannot accept your own answer","cannot revoke old vote":"sorry, older votes cannot be revoked","please confirm offensive":"are you sure this post is offensive, contains spam, advertising, malicious remarks, etc.?","flag offensive cap exhausted":"sorry, you've used up todays cap of flagging offensive messages ","confirm delete":"are you sure you want to delete this?","anonymous users cannot delete/undelete":"sorry, anonymous users cannot delete or undelete posts","post recovered":"your post is now restored!","post deleted":"your post has been deleted","confirm delete comment":"do you really want to delete this comment?","can write":"have ","tablimits info":"up to 5 tags, no more than 20 characters each","content minchars":"please enter more than {0} characters","title minchars":"please enter at least {0} characters",characters:"characters left","cannot vote for own posts":"sorry, you cannot vote for your own posts","cannot flag message as offensive twice":"cannot flag message as offensive twice ",">100 points required to downvote":">100 points required to downvote "};var i18nEs={"insufficient privilege":"privilegio insuficiente","cannot pick own answer as best":"no puede escoger su propia respuesta como la mejor","anonymous users cannot select favorite questions":"usuarios anonimos no pueden seleccionar","please login":"por favor inicie sesi�n","anonymous users cannot vote":"usuarios an�nimos no pueden votar",">15 points requried to upvote":">15 puntos requeridos para votar positivamente",">100 points required to downvote":">100 puntos requeridos para votar negativamente","please see":"por favor vea","cannot vote for own posts":"no se puede votar por sus propias publicaciones","daily vote cap exhausted":"cuota de votos diarios excedida","cannot revoke old vote":"no puede revocar un voto viejo","please confirm offensive":"por favor confirme ofensiva","anonymous users cannot flag offensive posts":"usuarios an�nimos no pueden marcar publicaciones como ofensivas","cannot flag message as offensive twice":"no puede marcar mensaje como ofensivo dos veces","flag offensive cap exhausted":"cuota para marcar ofensivas ha sido excedida","need >15 points to report spam":"necesita >15 puntos para reportar spam","confirm delete":"�Est� seguro que desea borrar esto?","anonymous users cannot delete/undelete":"usuarios an�nimos no pueden borrar o recuperar publicaciones","post recovered":"publicaci�n recuperada","post deleted":"publicaci�n borrada?","add comment":"agregar comentario","community karma points":"reputaci�n comunitaria","to comment, need":"para comentar, necesita reputaci�n","delete this comment":"borrar este comentario","hide comments":"ocultar comentarios","add a comment":"agregar comentarios",comments:"comentarios","confirm delete comment":"�Realmente desea borrar este comentario?",characters:"caracteres faltantes","can write":"tiene ","click to close":"haga click para cerrar","loading...":"cargando...","tags cannot be empty":"las etiquetas no pueden estar vac�as","tablimits info":"hasta 5 etiquetas de no mas de 20 caracteres cada una","content cannot be empty":"el contenido no puede estar vac�o","content minchars":"por favor introduzca mas de {0} caracteres","please enter title":"por favor ingrese un t�tulo","title minchars":"por favor introduzca al menos {0} caracteres","delete":"borrar",undelete:"recuperar",bold:"negrita",italic:"cursiva",link:"enlace",quote:"citar","preformatted text":"texto preformateado",image:"imagen","numbered list":"lista numerada","bulleted list":"lista no numerada",heading:"??","horizontal bar":"barra horizontal",undo:"deshacer",redo:"rehacer","enter image url":'introduzca la URL de la imagen, por ejemplo?<br />http://www.example.com/image.jpg   "titulo de imagen"',"enter url":'introduzca direcciones web, ejemplo?<br />http://www.cnprog.com/   "titulo del enlace"</p>"',"upload image":"cargar imagen?","questions/":"preguntas/","vote/":"votar/"};var i18n={en:i18nEn,zh_CN:i18nZh,es:i18nEs};var i18n_dict=i18n[i18nLang];(function(c){var h,i;var d=0;var a=32;var e;c.fn.TextAreaResizer=function(){return this.each(function(){h=c(this).addClass("processed"),i=null;c(this).wrap('<div class="resizable-textarea"><span></span></div>').parent().append(c('<div class="grippie"></div>').bind("mousedown",{el:this},b));var k=c("div.grippie",c(this).parent())[0];k.style.marginRight=(k.offsetWidth-c(this)[0].offsetWidth)+"px"})};function b(k){h=c(k.data.el);h.blur();d=j(k).y;i=h.height()-d;h.css("opacity",0.25);c(document).mousemove(g).mouseup(f);return false}function g(m){var k=j(m).y;var l=i+k;if(d>=(k)){l-=5}d=k;l=Math.max(a,l);h.height(l+"px");if(l<a){f(m)}return false}function f(k){c(document).unbind("mousemove",g).unbind("mouseup",f);h.css("opacity",1);h.focus();h=null;i=null;d=0}function j(k){return{x:k.clientX+document.documentElement.scrollLeft,y:k.clientY+document.documentElement.scrollTop}}})(jQuery);(function(a){a.fn.extend({autocomplete:function(b,c){var d=typeof b=="string";c=a.extend({},a.Autocompleter.defaults,{url:d?b:null,data:d?null:b,delay:d?a.Autocompleter.defaults.delay:10,max:c&&!c.scroll?10:150},c);c.highlight=c.highlight||function(e){return e};c.formatMatch=c.formatMatch||c.formatItem;return this.each(function(){new a.Autocompleter(this,c)})},result:function(b){return this.bind("result",b)},search:function(b){return this.trigger("search",[b])},flushCache:function(){return this.trigger("flushCache")},setOptions:function(b){return this.trigger("setOptions",[b])},unautocomplete:function(){return this.trigger("unautocomplete")}});a.Autocompleter=function(l,g){var c={UP:38,DOWN:40,DEL:46,TAB:9,RETURN:13,ESC:27,COMMA:188,PAGEUP:33,PAGEDOWN:34,BACKSPACE:8};var b=a(l).attr("autocomplete","off").addClass(g.inputClass);var j;var p="";var m=a.Autocompleter.Cache(g);var e=0;var u;var x={mouseDownOnSelect:false};var r=a.Autocompleter.Select(g,l,d,x);var w;a.browser.opera&&a(l.form).bind("submit.autocomplete",function(){if(w){w=false;return false}});b.bind((a.browser.opera?"keypress":"keydown")+".autocomplete",function(y){u=y.keyCode;switch(y.keyCode){case c.UP:y.preventDefault();if(r.visible()){r.prev()}else{t(0,true)}break;case c.DOWN:y.preventDefault();if(r.visible()){r.next()}else{t(0,true)}break;case c.PAGEUP:y.preventDefault();if(r.visible()){r.pageUp()}else{t(0,true)}break;case c.PAGEDOWN:y.preventDefault();if(r.visible()){r.pageDown()}else{t(0,true)}break;case g.multiple&&a.trim(g.multipleSeparator)==","&&c.COMMA:case c.TAB:case c.RETURN:if(d()){y.preventDefault();w=true;return false}break;case c.ESC:r.hide();break;default:clearTimeout(j);j=setTimeout(t,g.delay);break}}).focus(function(){e++}).blur(function(){e=0;if(!x.mouseDownOnSelect){s()}}).click(function(){if(e++>1&&!r.visible()){t(0,true)}}).bind("search",function(){var y=(arguments.length>1)?arguments[1]:null;function z(D,C){var A;if(C&&C.length){for(var B=0;B<C.length;B++){if(C[B].result.toLowerCase()==D.toLowerCase()){A=C[B];break}}}if(typeof y=="function"){y(A)}else{b.trigger("result",A&&[A.data,A.value])}}a.each(h(b.val()),function(A,B){f(B,z,z)})}).bind("flushCache",function(){m.flush()}).bind("setOptions",function(){a.extend(g,arguments[1]);if("data" in arguments[1]){m.populate()}}).bind("unautocomplete",function(){r.unbind();b.unbind();a(l.form).unbind(".autocomplete")});function d(){var z=r.selected();if(!z){return false}var y=z.result;p=y;if(g.multiple){var A=h(b.val());if(A.length>1){y=A.slice(0,A.length-1).join(g.multipleSeparator)+g.multipleSeparator+y}y+=g.multipleSeparator}b.val(y);v();b.trigger("result",[z.data,z.value]);return true}function t(A,z){if(u==c.DEL){r.hide();return}var y=b.val();if(!z&&y==p){return}p=y;y=i(y);if(y.length>=g.minChars){b.addClass(g.loadingClass);if(!g.matchCase){y=y.toLowerCase()}f(y,k,v)}else{n();r.hide()}}function h(z){if(!z){return[""]}var A=z.split(g.multipleSeparator);var y=[];a.each(A,function(B,C){if(a.trim(C)){y[B]=a.trim(C)}});return y}function i(y){if(!g.multiple){return y}var z=h(y);return z[z.length-1]}function q(y,z){if(g.autoFill&&(i(b.val()).toLowerCase()==y.toLowerCase())&&u!=c.BACKSPACE){b.val(b.val()+z.substring(i(p).length));a.Autocompleter.Selection(l,p.length,p.length+z.length)}}function s(){clearTimeout(j);j=setTimeout(v,200)}function v(){var y=r.visible();r.hide();clearTimeout(j);n();if(g.mustMatch){b.search(function(z){if(!z){if(g.multiple){var A=h(b.val()).slice(0,-1);b.val(A.join(g.multipleSeparator)+(A.length?g.multipleSeparator:""))}else{b.val("")}}})}if(y){a.Autocompleter.Selection(l,l.value.length,l.value.length)}}function k(z,y){if(y&&y.length&&e){n();r.display(y,z);q(z,y[0].value);r.show()}else{v()}}function f(z,B,y){if(!g.matchCase){z=z.toLowerCase()}var A=m.load(z);if(A&&A.length){B(z,A)}else{if((typeof g.url=="string")&&(g.url.length>0)){var C={timestamp:+new Date()};a.each(g.extraParams,function(D,E){C[D]=typeof E=="function"?E():E});a.ajax({mode:"abort",port:"autocomplete"+l.name,dataType:g.dataType,url:g.url,data:a.extend({q:i(z),limit:g.max},C),success:function(E){var D=g.parse&&g.parse(E)||o(E);m.add(z,D);B(z,D)}})}else{r.emptyList();y(z)}}}function o(B){var y=[];var A=B.split("\n");for(var z=0;z<A.length;z++){var C=a.trim(A[z]);if(C){C=C.split("|");y[y.length]={data:C,value:C[0],result:g.formatResult&&g.formatResult(C,C[0])||C[0]}}}return y}function n(){b.removeClass(g.loadingClass)}};a.Autocompleter.defaults={inputClass:"ac_input",resultsClass:"ac_results",loadingClass:"ac_loading",minChars:1,delay:400,matchCase:false,matchSubset:true,matchContains:false,cacheLength:10,max:100,mustMatch:false,extraParams:{},selectFirst:true,formatItem:function(b){return b[0]},formatMatch:null,autoFill:false,width:0,multiple:false,multipleSeparator:", ",highlight:function(c,b){return c.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)("+b.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi,"\\$1")+")(?![^<>]*>)(?![^&;]+;)","gi"),"<strong>$1</strong>")},scroll:true,scrollHeight:180};a.Autocompleter.Cache=function(c){var f={};var d=0;function h(l,k){if(!c.matchCase){l=l.toLowerCase()}var j=l.indexOf(k);if(j==-1){return false}return j==0||c.matchContains}function g(j,i){if(d>c.cacheLength){b()}if(!f[j]){d++}f[j]=i}function e(){if(!c.data){return false}var k={},j=0;if(!c.url){c.cacheLength=1}k[""]=[];for(var m=0,l=c.data.length;m<l;m++){var p=c.data[m];p=(typeof p=="string")?[p]:p;var o=c.formatMatch(p,m+1,c.data.length);if(o===false){continue}var n=o.charAt(0).toLowerCase();if(!k[n]){k[n]=[]}var q={value:o,data:p,result:c.formatResult&&c.formatResult(p)||o};k[n].push(q);if(j++<c.max){k[""].push(q)}}a.each(k,function(r,s){c.cacheLength++;g(r,s)})}setTimeout(e,25);function b(){f={};d=0}return{flush:b,add:g,populate:e,load:function(n){if(!c.cacheLength||!d){return null}if(!c.url&&c.matchContains){var m=[];for(var j in f){if(j.length>0){var o=f[j];a.each(o,function(p,k){if(h(k.value,n)){m.push(k)}})}}return m}else{if(f[n]){return f[n]}else{if(c.matchSubset){for(var l=n.length-1;l>=c.minChars;l--){var o=f[n.substr(0,l)];if(o){var m=[];a.each(o,function(p,k){if(h(k.value,n)){m[m.length]=k}});return m}}}}}return null}}};a.Autocompleter.Select=function(e,j,l,p){var i={ACTIVE:"ac_over"};var k,f=-1,r,m="",s=true,c,o;function n(){if(!s){return}c=a("<div/>").hide().addClass(e.resultsClass).css("position","absolute").appendTo(document.body);o=a("<ul/>").appendTo(c).mouseover(function(t){if(q(t).nodeName&&q(t).nodeName.toUpperCase()=="LI"){f=a("li",o).removeClass(i.ACTIVE).index(q(t));a(q(t)).addClass(i.ACTIVE)}}).click(function(t){a(q(t)).addClass(i.ACTIVE);l();j.focus();return false}).mousedown(function(){p.mouseDownOnSelect=true}).mouseup(function(){p.mouseDownOnSelect=false});if(e.width>0){c.css("width",e.width)}s=false}function q(u){var t=u.target;while(t&&t.tagName!="LI"){t=t.parentNode}if(!t){return[]}return t}function h(t){k.slice(f,f+1).removeClass(i.ACTIVE);g(t);var v=k.slice(f,f+1).addClass(i.ACTIVE);if(e.scroll){var u=0;k.slice(0,f).each(function(){u+=this.offsetHeight});if((u+v[0].offsetHeight-o.scrollTop())>o[0].clientHeight){o.scrollTop(u+v[0].offsetHeight-o.innerHeight())}else{if(u<o.scrollTop()){o.scrollTop(u)}}}}function g(t){f+=t;if(f<0){f=k.size()-1}else{if(f>=k.size()){f=0}}}function b(t){return e.max&&e.max<t?e.max:t}function d(){o.empty();var u=b(r.length);for(var v=0;v<u;v++){if(!r[v]){continue}var w=e.formatItem(r[v].data,v+1,u,r[v].value,m);if(w===false){continue}var t=a("<li/>").html(e.highlight(w,m)).addClass(v%2==0?"ac_even":"ac_odd").appendTo(o)[0];a.data(t,"ac_data",r[v])}k=o.find("li");if(e.selectFirst){k.slice(0,1).addClass(i.ACTIVE);f=0}if(a.fn.bgiframe){o.bgiframe()}}return{display:function(u,t){n();r=u;m=t;d()},next:function(){h(1)},prev:function(){h(-1)},pageUp:function(){if(f!=0&&f-8<0){h(-f)}else{h(-8)}},pageDown:function(){if(f!=k.size()-1&&f+8>k.size()){h(k.size()-1-f)}else{h(8)}},hide:function(){c&&c.hide();k&&k.removeClass(i.ACTIVE);f=-1},visible:function(){return c&&c.is(":visible")},current:function(){return this.visible()&&(k.filter("."+i.ACTIVE)[0]||e.selectFirst&&k[0])},show:function(){var v=a(j).offset();c.css({width:typeof e.width=="string"||e.width>0?e.width:a(j).width(),top:v.top+j.offsetHeight,left:v.left}).show();if(e.scroll){o.scrollTop(0);o.css({maxHeight:e.scrollHeight,overflow:"auto"});if(a.browser.msie&&typeof document.body.style.maxHeight==="undefined"){var t=0;k.each(function(){t+=this.offsetHeight});var u=t>e.scrollHeight;o.css("height",u?e.scrollHeight:t);if(!u){k.width(o.width()-parseInt(k.css("padding-left"))-parseInt(k.css("padding-right")))}}}},selected:function(){var t=k&&k.filter("."+i.ACTIVE).removeClass(i.ACTIVE);return t&&t.length&&a.data(t[0],"ac_data")},emptyList:function(){o&&o.empty()},unbind:function(){c&&c.remove()}}};a.Autocompleter.Selection=function(d,e,c){if(d.createTextRange){var b=d.createTextRange();b.collapse(true);b.moveStart("character",e);b.moveEnd("character",c);b.select()}else{if(d.setSelectionRange){d.setSelectionRange(e,c)}else{if(d.selectionStart){d.selectionStart=e;d.selectionEnd=c}}}d.focus()}})(jQuery);var notify=function(){var a=false;return{show:function(b){if(b){$("body").css("margin-top","2.2em");$(".notify span").html(b)}$(".notify").fadeIn("slow");a=true},close:function(b){if(b){$.post(scriptUrl+$.i18n._("messages/")+$.i18n._("markread/"),{formdata:"required"})}$(".notify").fadeOut("fast");$("body").css("margin-top","0");a=false},isVisible:function(){return a}}}();
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/osqa.question.js b/forum/modules/template_loader.py/forum/skins/default/media/js/osqa.question.js
new file mode 100644 (file)
index 0000000..38347d5
--- /dev/null
@@ -0,0 +1,6 @@
+$(function () {
+    $('div#editor_side_bar').hide();
+
+    $('#editor').focus(function(){ $('div#editor_side_bar').fadeIn('slow') });
+    $('#editor').blur(function(){ $('div#editor_side_bar').fadeOut('slow') });
+});
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/se_hilite.js b/forum/modules/template_loader.py/forum/skins/default/media/js/se_hilite.js
new file mode 100644 (file)
index 0000000..42e99c8
--- /dev/null
@@ -0,0 +1 @@
+Hilite={elementid:"content",exact:true,max_nodes:1000,onload:true,style_name:"hilite",style_name_suffix:true,debug_referrer:""};Hilite.search_engines=[["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 --git a/forum/modules/template_loader.py/forum/skins/default/media/js/se_hilite_src.js b/forum/modules/template_loader.py/forum/skins/default/media/js/se_hilite_src.js
new file mode 100644 (file)
index 0000000..b604f15
--- /dev/null
@@ -0,0 +1,273 @@
+/**
+ * Search Engine Keyword Highlight (http://fucoder.com/code/se-hilite/)
+ *
+ * This module can be imported by any HTML page, and it would analyse the
+ * referrer for search engine keywords, and then highlight those keywords on
+ * the page, by wrapping them around <span class="hilite">...</span> tags.
+ * Document can then define styles else where to provide visual feedbacks.
+ *
+ * Usage:
+ *
+ *   In HTML. Add the following line towards the end of the document.
+ *
+ *     <script type="text/javascript" src="se_hilite.js"></script>
+ *
+ *   In CSS, define the following style:
+ *
+ *     .hilite { background-color: #ff0; }
+ *
+ *   If Hilite.style_name_suffix is true, then define the follow styles:
+ *
+ *     .hilite1 { background-color: #ff0; }
+ *     .hilite2 { background-color: #f0f; }
+ *     .hilite3 { background-color: #0ff; }
+ *     .hilite4 ...
+ *
+ * @author Scott Yang <http://scott.yang.id.au/>
+ * @version 1.5
+ */
+
+// Configuration:
+Hilite = {
+    /**
+     * Element ID to be highlighted. If set, then only content inside this DOM
+     * element will be highlighted, otherwise everything inside document.body
+     * will be searched.
+     */
+    elementid: 'content',
+    
+    /**
+     * Whether we are matching an exact word. For example, searching for
+     * "highlight" will only match "highlight" but not "highlighting" if exact
+     * is set to true.
+     */
+    exact: true,
+
+    /**
+     * Maximum number of DOM nodes to test, before handing the control back to
+     * the GUI thread. This prevents locking up the UI when parsing and
+     * replacing inside a large document.
+     */
+    max_nodes: 1000,
+
+    /**
+     * Whether to automatically hilite a section of the HTML document, by
+     * binding the "Hilite.hilite()" to window.onload() event. If this
+     * attribute is set to false, you can still manually trigger the hilite by
+     * calling Hilite.hilite() in Javascript after document has been fully
+     * loaded.
+     */
+    onload: true,
+
+    /**
+     * Name of the style to be used. Default to 'hilite'.
+     */
+    style_name: 'hilite',
+    
+    /**
+     * Whether to use different style names for different search keywords by
+     * appending a number starting from 1, i.e. hilite1, hilite2, etc.
+     */
+    style_name_suffix: true,
+
+    /**
+     * Set it to override the document.referrer string. Used for debugging
+     * only.
+     */
+    debug_referrer: ''
+};
+
+Hilite.search_engines = [
+    ['google\\.', 'q'],                             // Google
+    ['search\\.yahoo\\.', 'p'],                     // Yahoo
+    ['search\\.msn\\.', 'q'],                       // MSN
+    ['search\\.live\\.', 'query'],                  // MSN Live
+    ['search\\.aol\\.', 'userQuery'],               // AOL
+    ['ask\\.com', 'q'],                             // Ask.com
+    ['altavista\\.', 'q'],                          // AltaVista
+    ['feedster\\.', 'q'],                           // Feedster
+    ['search\\.lycos\\.', 'q'],                     // Lycos
+    ['alltheweb\\.', 'q'],                          // AllTheWeb
+    ['technorati\\.com/search/([^\\?/]+)', 1],      // Technorati
+    ['dogpile\\.com/info\\.dogpl/search/web/([^\\?/]+)', 1, true] // DogPile
+];
+
+/**
+ * Decode the referrer string and return a list of search keywords.
+ */
+Hilite.decodeReferrer = function(referrer) {
+    var query = null;
+    var regex = new RegExp('');
+
+    for (var i = 0; i < Hilite.search_engines.length; i ++) {
+        var se = Hilite.search_engines[i];
+        regex.compile('^http://(www\\.)?' + se[0], 'i');
+        var match = referrer.match(regex);
+        if (match) {
+            var result;
+            if (isNaN(se[1])) {
+                result = Hilite.decodeReferrerQS(referrer, se[1]);
+            } else {
+                result = match[se[1] + 1];
+            }
+            if (result) {
+                result = decodeURIComponent(result);
+                // XXX: DogPile's URI requires decoding twice.
+                if (se.length > 2 && se[2])
+                    result = decodeURIComponent(result);
+                result = result.replace(/\'|"/g, '');
+                result = result.split(/[\s,\+\.]+/);
+                return result;
+            }
+            break;
+        }
+    }
+    return null;
+};
+
+Hilite.decodeReferrerQS = function(referrer, match) {
+    var idx = referrer.indexOf('?');
+    var idx2;
+    if (idx >= 0) {
+        var qs = new String(referrer.substring(idx + 1));
+        idx  = 0;
+        idx2 = 0;
+        while ((idx >= 0) && ((idx2 = qs.indexOf('=', idx)) >= 0)) {
+            var key, val;
+            key = qs.substring(idx, idx2);
+            idx = qs.indexOf('&', idx2) + 1;
+            if (key == match) {
+                if (idx <= 0) {
+                    return qs.substring(idx2+1);
+                } else {
+                    return qs.substring(idx2+1, idx - 1);
+                }
+            }
+            else if (idx <=0) {
+                return null;
+            }
+        }
+    }
+    return null;
+};
+
+/**
+ * Highlight a DOM element with a list of keywords.
+ */
+Hilite.hiliteElement = function(elm, query) {
+    if (!query || elm.childNodes.length == 0)
+       return;
+
+    var qre = new Array();
+    for (var i = 0; i < query.length; i ++) {
+        query[i] = query[i].toLowerCase();
+        if (Hilite.exact)
+            qre.push('\\b'+query[i]+'\\b');
+        else
+            qre.push(query[i]);
+    }
+
+    qre = new RegExp(qre.join("|"), "i");
+
+    var stylemapper = {};
+    for (var i = 0; i < query.length; i ++) {
+        if (Hilite.style_name_suffix)
+            stylemapper[query[i]] = Hilite.style_name+(i+1);
+        else
+            stylemapper[query[i]] = Hilite.style_name;
+    }
+
+    var textproc = function(node) {
+        var match = qre.exec(node.data);
+        if (match) {
+            var val = match[0];
+            var k = '';
+            var node2 = node.splitText(match.index);
+            var node3 = node2.splitText(val.length);
+            var span = node.ownerDocument.createElement('SPAN');
+            node.parentNode.replaceChild(span, node2);
+            span.className = stylemapper[val.toLowerCase()];
+            span.appendChild(node2);
+            return span;
+        } else {
+            return node;
+        }
+    };
+    Hilite.walkElements(elm.childNodes[0], 1, textproc);
+};
+
+/**
+ * Highlight a HTML document using keywords extracted from document.referrer.
+ * This is the main function to be called to perform search engine highlight
+ * on a document.
+ *
+ * Currently it would check for DOM element 'content', element 'container' and
+ * then document.body in that order, so it only highlights appropriate section
+ * on WordPress and Movable Type pages.
+ */
+Hilite.hilite = function() {
+    // If 'debug_referrer' then we will use that as our referrer string
+    // instead.
+    var q = Hilite.debug_referrer ? Hilite.debug_referrer : document.referrer;
+    var e = null;
+    q = Hilite.decodeReferrer(q);
+    if (q && ((Hilite.elementid && 
+               (e = document.getElementById(Hilite.elementid))) || 
+              (e = document.body)))
+    {
+       Hilite.hiliteElement(e, q);
+    }
+};
+
+Hilite.walkElements = function(node, depth, textproc) {
+    var skipre = /^(script|style|textarea)/i;
+    var count = 0;
+    while (node && depth > 0) {
+        count ++;
+        if (count >= Hilite.max_nodes) {
+            var handler = function() {
+                Hilite.walkElements(node, depth, textproc);
+            };
+            setTimeout(handler, 50);
+            return;
+        }
+
+        if (node.nodeType == 1) { // ELEMENT_NODE
+            if (!skipre.test(node.tagName) && node.childNodes.length > 0) {
+                node = node.childNodes[0];
+                depth ++;
+                continue;
+            }
+        } else if (node.nodeType == 3) { // TEXT_NODE
+            node = textproc(node);
+        }
+
+        if (node.nextSibling) {
+            node = node.nextSibling;
+        } else {
+            while (depth > 0) {
+                node = node.parentNode;
+                depth --;
+                if (node.nextSibling) {
+                    node = node.nextSibling;
+                    break;
+                }
+            }
+        }
+    }
+};
+
+// Trigger the highlight using the onload handler.
+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();
+        };
+    }
+}
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/ui.core.js b/forum/modules/template_loader.py/forum/skins/default/media/js/ui.core.js
new file mode 100644 (file)
index 0000000..5493e0a
--- /dev/null
@@ -0,0 +1,519 @@
+/*
+ * jQuery UI 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI
+ */
+;jQuery.ui || (function($) {
+
+var _remove = $.fn.remove,
+       isFF2 = $.browser.mozilla && (parseFloat($.browser.version) < 1.9);
+
+//Helper functions and ui object
+$.ui = {
+       version: "1.7.2",
+
+       // $.ui.plugin is deprecated.  Use the proxy pattern instead.
+       plugin: {
+               add: function(module, option, set) {
+                       var proto = $.ui[module].prototype;
+                       for(var i in set) {
+                               proto.plugins[i] = proto.plugins[i] || [];
+                               proto.plugins[i].push([option, set[i]]);
+                       }
+               },
+               call: function(instance, name, args) {
+                       var set = instance.plugins[name];
+                       if(!set || !instance.element[0].parentNode) { return; }
+
+                       for (var i = 0; i < set.length; i++) {
+                               if (instance.options[set[i][0]]) {
+                                       set[i][1].apply(instance.element, args);
+                               }
+                       }
+               }
+       },
+
+       contains: function(a, b) {
+               return document.compareDocumentPosition
+                       ? a.compareDocumentPosition(b) & 16
+                       : a !== b && a.contains(b);
+       },
+
+       hasScroll: function(el, a) {
+
+               //If overflow is hidden, the element might have extra content, but the user wants to hide it
+               if ($(el).css('overflow') == 'hidden') { return false; }
+
+               var scroll = (a && a == 'left') ? 'scrollLeft' : 'scrollTop',
+                       has = false;
+
+               if (el[scroll] > 0) { return true; }
+
+               // TODO: determine which cases actually cause this to happen
+               // if the element doesn't have the scroll set, see if it's possible to
+               // set the scroll
+               el[scroll] = 1;
+               has = (el[scroll] > 0);
+               el[scroll] = 0;
+               return has;
+       },
+
+       isOverAxis: function(x, reference, size) {
+               //Determines when x coordinate is over "b" element axis
+               return (x > reference) && (x < (reference + size));
+       },
+
+       isOver: function(y, x, top, left, height, width) {
+               //Determines when x, y coordinates is over "b" element
+               return $.ui.isOverAxis(y, top, height) && $.ui.isOverAxis(x, left, width);
+       },
+
+       keyCode: {
+               BACKSPACE: 8,
+               CAPS_LOCK: 20,
+               COMMA: 188,
+               CONTROL: 17,
+               DELETE: 46,
+               DOWN: 40,
+               END: 35,
+               ENTER: 13,
+               ESCAPE: 27,
+               HOME: 36,
+               INSERT: 45,
+               LEFT: 37,
+               NUMPAD_ADD: 107,
+               NUMPAD_DECIMAL: 110,
+               NUMPAD_DIVIDE: 111,
+               NUMPAD_ENTER: 108,
+               NUMPAD_MULTIPLY: 106,
+               NUMPAD_SUBTRACT: 109,
+               PAGE_DOWN: 34,
+               PAGE_UP: 33,
+               PERIOD: 190,
+               RIGHT: 39,
+               SHIFT: 16,
+               SPACE: 32,
+               TAB: 9,
+               UP: 38
+       }
+};
+
+// WAI-ARIA normalization
+if (isFF2) {
+       var attr = $.attr,
+               removeAttr = $.fn.removeAttr,
+               ariaNS = "http://www.w3.org/2005/07/aaa",
+               ariaState = /^aria-/,
+               ariaRole = /^wairole:/;
+
+       $.attr = function(elem, name, value) {
+               var set = value !== undefined;
+
+               return (name == 'role'
+                       ? (set
+                               ? attr.call(this, elem, name, "wairole:" + value)
+                               : (attr.apply(this, arguments) || "").replace(ariaRole, ""))
+                       : (ariaState.test(name)
+                               ? (set
+                                       ? elem.setAttributeNS(ariaNS,
+                                               name.replace(ariaState, "aaa:"), value)
+                                       : attr.call(this, elem, name.replace(ariaState, "aaa:")))
+                               : attr.apply(this, arguments)));
+       };
+
+       $.fn.removeAttr = function(name) {
+               return (ariaState.test(name)
+                       ? this.each(function() {
+                               this.removeAttributeNS(ariaNS, name.replace(ariaState, ""));
+                       }) : removeAttr.call(this, name));
+       };
+}
+
+//jQuery plugins
+$.fn.extend({
+       remove: function() {
+               // Safari has a native remove event which actually removes DOM elements,
+               // so we have to use triggerHandler instead of trigger (#3037).
+               $("*", this).add(this).each(function() {
+                       $(this).triggerHandler("remove");
+               });
+               return _remove.apply(this, arguments );
+       },
+
+       enableSelection: function() {
+               return this
+                       .attr('unselectable', 'off')
+                       .css('MozUserSelect', '')
+                       .unbind('selectstart.ui');
+       },
+
+       disableSelection: function() {
+               return this
+                       .attr('unselectable', 'on')
+                       .css('MozUserSelect', 'none')
+                       .bind('selectstart.ui', function() { return false; });
+       },
+
+       scrollParent: function() {
+               var scrollParent;
+               if(($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
+                       scrollParent = this.parents().filter(function() {
+                               return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
+                       }).eq(0);
+               } else {
+                       scrollParent = this.parents().filter(function() {
+                               return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
+                       }).eq(0);
+               }
+
+               return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
+       }
+});
+
+
+//Additional selectors
+$.extend($.expr[':'], {
+       data: function(elem, i, match) {
+               return !!$.data(elem, match[3]);
+       },
+
+       focusable: function(element) {
+               var nodeName = element.nodeName.toLowerCase(),
+                       tabIndex = $.attr(element, 'tabindex');
+               return (/input|select|textarea|button|object/.test(nodeName)
+                       ? !element.disabled
+                       : 'a' == nodeName || 'area' == nodeName
+                               ? element.href || !isNaN(tabIndex)
+                               : !isNaN(tabIndex))
+                       // the element and all of its ancestors must be visible
+                       // the browser may report that the area is hidden
+                       && !$(element)['area' == nodeName ? 'parents' : 'closest'](':hidden').length;
+       },
+
+       tabbable: function(element) {
+               var tabIndex = $.attr(element, 'tabindex');
+               return (isNaN(tabIndex) || tabIndex >= 0) && $(element).is(':focusable');
+       }
+});
+
+
+// $.widget is a factory to create jQuery plugins
+// taking some boilerplate code out of the plugin code
+function getter(namespace, plugin, method, args) {
+       function getMethods(type) {
+               var methods = $[namespace][plugin][type] || [];
+               return (typeof methods == 'string' ? methods.split(/,?\s+/) : methods);
+       }
+
+       var methods = getMethods('getter');
+       if (args.length == 1 && typeof args[0] == 'string') {
+               methods = methods.concat(getMethods('getterSetter'));
+       }
+       return ($.inArray(method, methods) != -1);
+}
+
+$.widget = function(name, prototype) {
+       var namespace = name.split(".")[0];
+       name = name.split(".")[1];
+
+       // create plugin method
+       $.fn[name] = function(options) {
+               var isMethodCall = (typeof options == 'string'),
+                       args = Array.prototype.slice.call(arguments, 1);
+
+               // prevent calls to internal methods
+               if (isMethodCall && options.substring(0, 1) == '_') {
+                       return this;
+               }
+
+               // handle getter methods
+               if (isMethodCall && getter(namespace, name, options, args)) {
+                       var instance = $.data(this[0], name);
+                       return (instance ? instance[options].apply(instance, args)
+                               : undefined);
+               }
+
+               // handle initialization and non-getter methods
+               return this.each(function() {
+                       var instance = $.data(this, name);
+
+                       // constructor
+                       (!instance && !isMethodCall &&
+                               $.data(this, name, new $[namespace][name](this, options))._init());
+
+                       // method call
+                       (instance && isMethodCall && $.isFunction(instance[options]) &&
+                               instance[options].apply(instance, args));
+               });
+       };
+
+       // create widget constructor
+       $[namespace] = $[namespace] || {};
+       $[namespace][name] = function(element, options) {
+               var self = this;
+
+               this.namespace = namespace;
+               this.widgetName = name;
+               this.widgetEventPrefix = $[namespace][name].eventPrefix || name;
+               this.widgetBaseClass = namespace + '-' + name;
+
+               this.options = $.extend({},
+                       $.widget.defaults,
+                       $[namespace][name].defaults,
+                       $.metadata && $.metadata.get(element)[name],
+                       options);
+
+               this.element = $(element)
+                       .bind('setData.' + name, function(event, key, value) {
+                               if (event.target == element) {
+                                       return self._setData(key, value);
+                               }
+                       })
+                       .bind('getData.' + name, function(event, key) {
+                               if (event.target == element) {
+                                       return self._getData(key);
+                               }
+                       })
+                       .bind('remove', function() {
+                               return self.destroy();
+                       });
+       };
+
+       // add widget prototype
+       $[namespace][name].prototype = $.extend({}, $.widget.prototype, prototype);
+
+       // TODO: merge getter and getterSetter properties from widget prototype
+       // and plugin prototype
+       $[namespace][name].getterSetter = 'option';
+};
+
+$.widget.prototype = {
+       _init: function() {},
+       destroy: function() {
+               this.element.removeData(this.widgetName)
+                       .removeClass(this.widgetBaseClass + '-disabled' + ' ' + this.namespace + '-state-disabled')
+                       .removeAttr('aria-disabled');
+       },
+
+       option: function(key, value) {
+               var options = key,
+                       self = this;
+
+               if (typeof key == "string") {
+                       if (value === undefined) {
+                               return this._getData(key);
+                       }
+                       options = {};
+                       options[key] = value;
+               }
+
+               $.each(options, function(key, value) {
+                       self._setData(key, value);
+               });
+       },
+       _getData: function(key) {
+               return this.options[key];
+       },
+       _setData: function(key, value) {
+               this.options[key] = value;
+
+               if (key == 'disabled') {
+                       this.element
+                               [value ? 'addClass' : 'removeClass'](
+                                       this.widgetBaseClass + '-disabled' + ' ' +
+                                       this.namespace + '-state-disabled')
+                               .attr("aria-disabled", value);
+               }
+       },
+
+       enable: function() {
+               this._setData('disabled', false);
+       },
+       disable: function() {
+               this._setData('disabled', true);
+       },
+
+       _trigger: function(type, event, data) {
+               var callback = this.options[type],
+                       eventName = (type == this.widgetEventPrefix
+                               ? type : this.widgetEventPrefix + type);
+
+               event = $.Event(event);
+               event.type = eventName;
+
+               // copy original event properties over to the new event
+               // this would happen if we could call $.event.fix instead of $.Event
+               // but we don't have a way to force an event to be fixed multiple times
+               if (event.originalEvent) {
+                       for (var i = $.event.props.length, prop; i;) {
+                               prop = $.event.props[--i];
+                               event[prop] = event.originalEvent[prop];
+                       }
+               }
+
+               this.element.trigger(event, data);
+
+               return !($.isFunction(callback) && callback.call(this.element[0], event, data) === false
+                       || event.isDefaultPrevented());
+       }
+};
+
+$.widget.defaults = {
+       disabled: false
+};
+
+
+/** Mouse Interaction Plugin **/
+
+$.ui.mouse = {
+       _mouseInit: function() {
+               var self = this;
+
+               this.element
+                       .bind('mousedown.'+this.widgetName, function(event) {
+                               return self._mouseDown(event);
+                       })
+                       .bind('click.'+this.widgetName, function(event) {
+                               if(self._preventClickEvent) {
+                                       self._preventClickEvent = false;
+                                       event.stopImmediatePropagation();
+                                       return false;
+                               }
+                       });
+
+               // Prevent text selection in IE
+               if ($.browser.msie) {
+                       this._mouseUnselectable = this.element.attr('unselectable');
+                       this.element.attr('unselectable', 'on');
+               }
+
+               this.started = false;
+       },
+
+       // TODO: make sure destroying one instance of mouse doesn't mess with
+       // other instances of mouse
+       _mouseDestroy: function() {
+               this.element.unbind('.'+this.widgetName);
+
+               // Restore text selection in IE
+               ($.browser.msie
+                       && this.element.attr('unselectable', this._mouseUnselectable));
+       },
+
+       _mouseDown: function(event) {
+               // don't let more than one widget handle mouseStart
+               // TODO: figure out why we have to use originalEvent
+               event.originalEvent = event.originalEvent || {};
+               if (event.originalEvent.mouseHandled) { return; }
+
+               // we may have missed mouseup (out of window)
+               (this._mouseStarted && this._mouseUp(event));
+
+               this._mouseDownEvent = event;
+
+               var self = this,
+                       btnIsLeft = (event.which == 1),
+                       elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
+               if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
+                       return true;
+               }
+
+               this.mouseDelayMet = !this.options.delay;
+               if (!this.mouseDelayMet) {
+                       this._mouseDelayTimer = setTimeout(function() {
+                               self.mouseDelayMet = true;
+                       }, this.options.delay);
+               }
+
+               if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
+                       this._mouseStarted = (this._mouseStart(event) !== false);
+                       if (!this._mouseStarted) {
+                               event.preventDefault();
+                               return true;
+                       }
+               }
+
+               // these delegates are required to keep context
+               this._mouseMoveDelegate = function(event) {
+                       return self._mouseMove(event);
+               };
+               this._mouseUpDelegate = function(event) {
+                       return self._mouseUp(event);
+               };
+               $(document)
+                       .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
+                       .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
+
+               // preventDefault() is used to prevent the selection of text here -
+               // however, in Safari, this causes select boxes not to be selectable
+               // anymore, so this fix is needed
+               ($.browser.safari || event.preventDefault());
+
+               event.originalEvent.mouseHandled = true;
+               return true;
+       },
+
+       _mouseMove: function(event) {
+               // IE mouseup check - mouseup happened when mouse was out of window
+               if ($.browser.msie && !event.button) {
+                       return this._mouseUp(event);
+               }
+
+               if (this._mouseStarted) {
+                       this._mouseDrag(event);
+                       return event.preventDefault();
+               }
+
+               if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
+                       this._mouseStarted =
+                               (this._mouseStart(this._mouseDownEvent, event) !== false);
+                       (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
+               }
+
+               return !this._mouseStarted;
+       },
+
+       _mouseUp: function(event) {
+               $(document)
+                       .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
+                       .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
+
+               if (this._mouseStarted) {
+                       this._mouseStarted = false;
+                       this._preventClickEvent = (event.target == this._mouseDownEvent.target);
+                       this._mouseStop(event);
+               }
+
+               return false;
+       },
+
+       _mouseDistanceMet: function(event) {
+               return (Math.max(
+                               Math.abs(this._mouseDownEvent.pageX - event.pageX),
+                               Math.abs(this._mouseDownEvent.pageY - event.pageY)
+                       ) >= this.options.distance
+               );
+       },
+
+       _mouseDelayMet: function(event) {
+               return this.mouseDelayMet;
+       },
+
+       // These are placeholder methods, to be overriden by extending plugin
+       _mouseStart: function(event) {},
+       _mouseDrag: function(event) {},
+       _mouseStop: function(event) {},
+       _mouseCapture: function(event) { return true; }
+};
+
+$.ui.mouse.defaults = {
+       cancel: null,
+       distance: 1,
+       delay: 0
+};
+
+})(jQuery);
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/ui.core.min.js b/forum/modules/template_loader.py/forum/skins/default/media/js/ui.core.min.js
new file mode 100644 (file)
index 0000000..d6bd405
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * jQuery UI 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI
+ */
+jQuery.ui||(function(c){var i=c.fn.remove,d=c.browser.mozilla&&(parseFloat(c.browser.version)<1.9);c.ui={version:"1.7.2",plugin:{add:function(k,l,n){var m=c.ui[k].prototype;for(var j in n){m.plugins[j]=m.plugins[j]||[];m.plugins[j].push([l,n[j]])}},call:function(j,l,k){var n=j.plugins[l];if(!n||!j.element[0].parentNode){return}for(var m=0;m<n.length;m++){if(j.options[n[m][0]]){n[m][1].apply(j.element,k)}}}},contains:function(k,j){return document.compareDocumentPosition?k.compareDocumentPosition(j)&16:k!==j&&k.contains(j)},hasScroll:function(m,k){if(c(m).css("overflow")=="hidden"){return false}var j=(k&&k=="left")?"scrollLeft":"scrollTop",l=false;if(m[j]>0){return true}m[j]=1;l=(m[j]>0);m[j]=0;return l},isOverAxis:function(k,j,l){return(k>j)&&(k<(j+l))},isOver:function(o,k,n,m,j,l){return c.ui.isOverAxis(o,n,j)&&c.ui.isOverAxis(k,m,l)},keyCode:{BACKSPACE:8,CAPS_LOCK:20,COMMA:188,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38}};if(d){var f=c.attr,e=c.fn.removeAttr,h="http://www.w3.org/2005/07/aaa",a=/^aria-/,b=/^wairole:/;c.attr=function(k,j,l){var m=l!==undefined;return(j=="role"?(m?f.call(this,k,j,"wairole:"+l):(f.apply(this,arguments)||"").replace(b,"")):(a.test(j)?(m?k.setAttributeNS(h,j.replace(a,"aaa:"),l):f.call(this,k,j.replace(a,"aaa:"))):f.apply(this,arguments)))};c.fn.removeAttr=function(j){return(a.test(j)?this.each(function(){this.removeAttributeNS(h,j.replace(a,""))}):e.call(this,j))}}c.fn.extend({remove:function(){c("*",this).add(this).each(function(){c(this).triggerHandler("remove")});return i.apply(this,arguments)},enableSelection:function(){return this.attr("unselectable","off").css("MozUserSelect","").unbind("selectstart.ui")},disableSelection:function(){return this.attr("unselectable","on").css("MozUserSelect","none").bind("selectstart.ui",function(){return false})},scrollParent:function(){var j;if((c.browser.msie&&(/(static|relative)/).test(this.css("position")))||(/absolute/).test(this.css("position"))){j=this.parents().filter(function(){return(/(relative|absolute|fixed)/).test(c.curCSS(this,"position",1))&&(/(auto|scroll)/).test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0)}else{j=this.parents().filter(function(){return(/(auto|scroll)/).test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0)}return(/fixed/).test(this.css("position"))||!j.length?c(document):j}});c.extend(c.expr[":"],{data:function(l,k,j){return !!c.data(l,j[3])},focusable:function(k){var l=k.nodeName.toLowerCase(),j=c.attr(k,"tabindex");return(/input|select|textarea|button|object/.test(l)?!k.disabled:"a"==l||"area"==l?k.href||!isNaN(j):!isNaN(j))&&!c(k)["area"==l?"parents":"closest"](":hidden").length},tabbable:function(k){var j=c.attr(k,"tabindex");return(isNaN(j)||j>=0)&&c(k).is(":focusable")}});function g(m,n,o,l){function k(q){var p=c[m][n][q]||[];return(typeof p=="string"?p.split(/,?\s+/):p)}var j=k("getter");if(l.length==1&&typeof l[0]=="string"){j=j.concat(k("getterSetter"))}return(c.inArray(o,j)!=-1)}c.widget=function(k,j){var l=k.split(".")[0];k=k.split(".")[1];c.fn[k]=function(p){var n=(typeof p=="string"),o=Array.prototype.slice.call(arguments,1);if(n&&p.substring(0,1)=="_"){return this}if(n&&g(l,k,p,o)){var m=c.data(this[0],k);return(m?m[p].apply(m,o):undefined)}return this.each(function(){var q=c.data(this,k);(!q&&!n&&c.data(this,k,new c[l][k](this,p))._init());(q&&n&&c.isFunction(q[p])&&q[p].apply(q,o))})};c[l]=c[l]||{};c[l][k]=function(o,n){var m=this;this.namespace=l;this.widgetName=k;this.widgetEventPrefix=c[l][k].eventPrefix||k;this.widgetBaseClass=l+"-"+k;this.options=c.extend({},c.widget.defaults,c[l][k].defaults,c.metadata&&c.metadata.get(o)[k],n);this.element=c(o).bind("setData."+k,function(q,p,r){if(q.target==o){return m._setData(p,r)}}).bind("getData."+k,function(q,p){if(q.target==o){return m._getData(p)}}).bind("remove",function(){return m.destroy()})};c[l][k].prototype=c.extend({},c.widget.prototype,j);c[l][k].getterSetter="option"};c.widget.prototype={_init:function(){},destroy:function(){this.element.removeData(this.widgetName).removeClass(this.widgetBaseClass+"-disabled "+this.namespace+"-state-disabled").removeAttr("aria-disabled")},option:function(l,m){var k=l,j=this;if(typeof l=="string"){if(m===undefined){return this._getData(l)}k={};k[l]=m}c.each(k,function(n,o){j._setData(n,o)})},_getData:function(j){return this.options[j]},_setData:function(j,k){this.options[j]=k;if(j=="disabled"){this.element[k?"addClass":"removeClass"](this.widgetBaseClass+"-disabled "+this.namespace+"-state-disabled").attr("aria-disabled",k)}},enable:function(){this._setData("disabled",false)},disable:function(){this._setData("disabled",true)},_trigger:function(l,m,n){var p=this.options[l],j=(l==this.widgetEventPrefix?l:this.widgetEventPrefix+l);m=c.Event(m);m.type=j;if(m.originalEvent){for(var k=c.event.props.length,o;k;){o=c.event.props[--k];m[o]=m.originalEvent[o]}}this.element.trigger(m,n);return !(c.isFunction(p)&&p.call(this.element[0],m,n)===false||m.isDefaultPrevented())}};c.widget.defaults={disabled:false};c.ui.mouse={_mouseInit:function(){var j=this;this.element.bind("mousedown."+this.widgetName,function(k){return j._mouseDown(k)}).bind("click."+this.widgetName,function(k){if(j._preventClickEvent){j._preventClickEvent=false;k.stopImmediatePropagation();return false}});if(c.browser.msie){this._mouseUnselectable=this.element.attr("unselectable");this.element.attr("unselectable","on")}this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName);(c.browser.msie&&this.element.attr("unselectable",this._mouseUnselectable))},_mouseDown:function(l){l.originalEvent=l.originalEvent||{};if(l.originalEvent.mouseHandled){return}(this._mouseStarted&&this._mouseUp(l));this._mouseDownEvent=l;var k=this,m=(l.which==1),j=(typeof this.options.cancel=="string"?c(l.target).parents().add(l.target).filter(this.options.cancel).length:false);if(!m||j||!this._mouseCapture(l)){return true}this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet){this._mouseDelayTimer=setTimeout(function(){k.mouseDelayMet=true},this.options.delay)}if(this._mouseDistanceMet(l)&&this._mouseDelayMet(l)){this._mouseStarted=(this._mouseStart(l)!==false);if(!this._mouseStarted){l.preventDefault();return true}}this._mouseMoveDelegate=function(n){return k._mouseMove(n)};this._mouseUpDelegate=function(n){return k._mouseUp(n)};c(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);(c.browser.safari||l.preventDefault());l.originalEvent.mouseHandled=true;return true},_mouseMove:function(j){if(c.browser.msie&&!j.button){return this._mouseUp(j)}if(this._mouseStarted){this._mouseDrag(j);return j.preventDefault()}if(this._mouseDistanceMet(j)&&this._mouseDelayMet(j)){this._mouseStarted=(this._mouseStart(this._mouseDownEvent,j)!==false);(this._mouseStarted?this._mouseDrag(j):this._mouseUp(j))}return !this._mouseStarted},_mouseUp:function(j){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._preventClickEvent=(j.target==this._mouseDownEvent.target);this._mouseStop(j)}return false},_mouseDistanceMet:function(j){return(Math.max(Math.abs(this._mouseDownEvent.pageX-j.pageX),Math.abs(this._mouseDownEvent.pageY-j.pageY))>=this.options.distance)},_mouseDelayMet:function(j){return this.mouseDelayMet},_mouseStart:function(j){},_mouseDrag:function(j){},_mouseStop:function(j){},_mouseCapture:function(j){return true}};c.ui.mouse.defaults={cancel:null,distance:1,delay:0}})(jQuery);
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/ui.datepicker.js b/forum/modules/template_loader.py/forum/skins/default/media/js/ui.datepicker.js
new file mode 100644 (file)
index 0000000..0ce166e
--- /dev/null
@@ -0,0 +1,1636 @@
+/*
+ * jQuery UI Datepicker 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Datepicker
+ *
+ * Depends:
+ *     ui.core.js
+ */
+
+(function($) { // hide the namespace
+
+$.extend($.ui, { datepicker: { version: "1.7.2" } });
+
+var PROP_NAME = 'datepicker';
+
+/* Date picker manager.
+   Use the singleton instance of this class, $.datepicker, to interact with the date picker.
+   Settings for (groups of) date pickers are maintained in an instance object,
+   allowing multiple different settings on the same page. */
+
+function Datepicker() {
+       this.debug = false; // Change this to true to start debugging
+       this._curInst = null; // The current instance in use
+       this._keyEvent = false; // If the last event was a key event
+       this._disabledInputs = []; // List of date picker inputs that have been disabled
+       this._datepickerShowing = false; // True if the popup picker is showing , false if not
+       this._inDialog = false; // True if showing within a "dialog", false if not
+       this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
+       this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
+       this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
+       this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
+       this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
+       this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
+       this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
+       this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
+       this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
+       this.regional = []; // Available regional settings, indexed by language code
+       this.regional[''] = { // Default regional settings
+               closeText: 'Done', // Display text for close link
+               prevText: 'Prev', // Display text for previous month link
+               nextText: 'Next', // Display text for next month link
+               currentText: 'Today', // Display text for current month link
+               monthNames: ['January','February','March','April','May','June',
+                       'July','August','September','October','November','December'], // Names of months for drop-down and formatting
+               monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
+               dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
+               dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
+               dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
+               dateFormat: 'mm/dd/yy', // See format options on parseDate
+               firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
+               isRTL: false // True if right-to-left language, false if left-to-right
+       };
+       this._defaults = { // Global defaults for all the date picker instances
+               showOn: 'focus', // 'focus' for popup on focus,
+                       // 'button' for trigger button, or 'both' for either
+               showAnim: 'show', // Name of jQuery animation for popup
+               showOptions: {}, // Options for enhanced animations
+               defaultDate: null, // Used when field is blank: actual date,
+                       // +/-number for offset from today, null for today
+               appendText: '', // Display text following the input box, e.g. showing the format
+               buttonText: '...', // Text for trigger button
+               buttonImage: '', // URL for trigger button image
+               buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
+               hideIfNoPrevNext: false, // True to hide next/previous month links
+                       // if not applicable, false to just disable them
+               navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
+               gotoCurrent: false, // True if today link goes back to current selection instead
+               changeMonth: false, // True if month can be selected directly, false if only prev/next
+               changeYear: false, // True if year can be selected directly, false if only prev/next
+               showMonthAfterYear: false, // True if the year select precedes month, false for month then year
+               yearRange: '-10:+10', // Range of years to display in drop-down,
+                       // either relative to current year (-nn:+nn) or absolute (nnnn:nnnn)
+               showOtherMonths: false, // True to show dates in other months, false to leave blank
+               calculateWeek: this.iso8601Week, // How to calculate the week of the year,
+                       // takes a Date and returns the number of the week for it
+               shortYearCutoff: '+10', // Short year values < this are in the current century,
+                       // > this are in the previous century,
+                       // string value starting with '+' for current year + value
+               minDate: null, // The earliest selectable date, or null for no limit
+               maxDate: null, // The latest selectable date, or null for no limit
+               duration: 'normal', // Duration of display/closure
+               beforeShowDay: null, // Function that takes a date and returns an array with
+                       // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
+                       // [2] = cell title (optional), e.g. $.datepicker.noWeekends
+               beforeShow: null, // Function that takes an input field and
+                       // returns a set of custom settings for the date picker
+               onSelect: null, // Define a callback function when a date is selected
+               onChangeMonthYear: null, // Define a callback function when the month or year is changed
+               onClose: null, // Define a callback function when the datepicker is closed
+               numberOfMonths: 1, // Number of months to show at a time
+               showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
+               stepMonths: 1, // Number of months to step back/forward
+               stepBigMonths: 12, // Number of months to step back/forward for the big links
+               altField: '', // Selector for an alternate field to store selected dates into
+               altFormat: '', // The date format to use for the alternate field
+               constrainInput: true, // The input is constrained by the current date format
+               showButtonPanel: false // True to show button panel, false to not show it
+       };
+       $.extend(this._defaults, this.regional['']);
+       this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
+}
+
+$.extend(Datepicker.prototype, {
+       /* Class name added to elements to indicate already configured with a date picker. */
+       markerClassName: 'hasDatepicker',
+
+       /* Debug logging (if enabled). */
+       log: function () {
+               if (this.debug)
+                       console.log.apply('', arguments);
+       },
+
+       /* Override the default settings for all instances of the date picker.
+          @param  settings  object - the new settings to use as defaults (anonymous object)
+          @return the manager object */
+       setDefaults: function(settings) {
+               extendRemove(this._defaults, settings || {});
+               return this;
+       },
+
+       /* Attach the date picker to a jQuery selection.
+          @param  target    element - the target input field or division or span
+          @param  settings  object - the new settings to use for this date picker instance (anonymous) */
+       _attachDatepicker: function(target, settings) {
+               // check for settings on the control itself - in namespace 'date:'
+               var inlineSettings = null;
+               for (var attrName in this._defaults) {
+                       var attrValue = target.getAttribute('date:' + attrName);
+                       if (attrValue) {
+                               inlineSettings = inlineSettings || {};
+                               try {
+                                       inlineSettings[attrName] = eval(attrValue);
+                               } catch (err) {
+                                       inlineSettings[attrName] = attrValue;
+                               }
+                       }
+               }
+               var nodeName = target.nodeName.toLowerCase();
+               var inline = (nodeName == 'div' || nodeName == 'span');
+               if (!target.id)
+                       target.id = 'dp' + (++this.uuid);
+               var inst = this._newInst($(target), inline);
+               inst.settings = $.extend({}, settings || {}, inlineSettings || {});
+               if (nodeName == 'input') {
+                       this._connectDatepicker(target, inst);
+               } else if (inline) {
+                       this._inlineDatepicker(target, inst);
+               }
+       },
+
+       /* Create a new instance object. */
+       _newInst: function(target, inline) {
+               var id = target[0].id.replace(/([:\[\]\.])/g, '\\\\$1'); // escape jQuery meta chars
+               return {id: id, input: target, // associated target
+                       selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
+                       drawMonth: 0, drawYear: 0, // month being drawn
+                       inline: inline, // is datepicker inline or not
+                       dpDiv: (!inline ? this.dpDiv : // presentation div
+                       $('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
+       },
+
+       /* Attach the date picker to an input field. */
+       _connectDatepicker: function(target, inst) {
+               var input = $(target);
+               inst.append = $([]);
+               inst.trigger = $([]);
+               if (input.hasClass(this.markerClassName))
+                       return;
+               var appendText = this._get(inst, 'appendText');
+               var isRTL = this._get(inst, 'isRTL');
+               if (appendText) {
+                       inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
+                       input[isRTL ? 'before' : 'after'](inst.append);
+               }
+               var showOn = this._get(inst, 'showOn');
+               if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
+                       input.focus(this._showDatepicker);
+               if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
+                       var buttonText = this._get(inst, 'buttonText');
+                       var buttonImage = this._get(inst, 'buttonImage');
+                       inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
+                               $('<img/>').addClass(this._triggerClass).
+                                       attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
+                               $('<button type="button"></button>').addClass(this._triggerClass).
+                                       html(buttonImage == '' ? buttonText : $('<img/>').attr(
+                                       { src:buttonImage, alt:buttonText, title:buttonText })));
+                       input[isRTL ? 'before' : 'after'](inst.trigger);
+                       inst.trigger.click(function() {
+                               if ($.datepicker._datepickerShowing && $.datepicker._lastInput == target)
+                                       $.datepicker._hideDatepicker();
+                               else
+                                       $.datepicker._showDatepicker(target);
+                               return false;
+                       });
+               }
+               input.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).
+                       bind("setData.datepicker", function(event, key, value) {
+                               inst.settings[key] = value;
+                       }).bind("getData.datepicker", function(event, key) {
+                               return this._get(inst, key);
+                       });
+               $.data(target, PROP_NAME, inst);
+       },
+
+       /* Attach an inline date picker to a div. */
+       _inlineDatepicker: function(target, inst) {
+               var divSpan = $(target);
+               if (divSpan.hasClass(this.markerClassName))
+                       return;
+               divSpan.addClass(this.markerClassName).append(inst.dpDiv).
+                       bind("setData.datepicker", function(event, key, value){
+                               inst.settings[key] = value;
+                       }).bind("getData.datepicker", function(event, key){
+                               return this._get(inst, key);
+                       });
+               $.data(target, PROP_NAME, inst);
+               this._setDate(inst, this._getDefaultDate(inst));
+               this._updateDatepicker(inst);
+               this._updateAlternate(inst);
+       },
+
+       /* Pop-up the date picker in a "dialog" box.
+          @param  input     element - ignored
+          @param  dateText  string - the initial date to display (in the current format)
+          @param  onSelect  function - the function(dateText) to call when a date is selected
+          @param  settings  object - update the dialog date picker instance's settings (anonymous object)
+          @param  pos       int[2] - coordinates for the dialog's position within the screen or
+                            event - with x/y coordinates or
+                            leave empty for default (screen centre)
+          @return the manager object */
+       _dialogDatepicker: function(input, dateText, onSelect, settings, pos) {
+               var inst = this._dialogInst; // internal instance
+               if (!inst) {
+                       var id = 'dp' + (++this.uuid);
+                       this._dialogInput = $('<input type="text" id="' + id +
+                               '" size="1" style="position: absolute; top: -100px;"/>');
+                       this._dialogInput.keydown(this._doKeyDown);
+                       $('body').append(this._dialogInput);
+                       inst = this._dialogInst = this._newInst(this._dialogInput, false);
+                       inst.settings = {};
+                       $.data(this._dialogInput[0], PROP_NAME, inst);
+               }
+               extendRemove(inst.settings, settings || {});
+               this._dialogInput.val(dateText);
+
+               this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
+               if (!this._pos) {
+                       var browserWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
+                       var browserHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
+                       var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
+                       var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
+                       this._pos = // should use actual width/height below
+                               [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
+               }
+
+               // move input on screen for focus, but hidden behind dialog
+               this._dialogInput.css('left', this._pos[0] + 'px').css('top', this._pos[1] + 'px');
+               inst.settings.onSelect = onSelect;
+               this._inDialog = true;
+               this.dpDiv.addClass(this._dialogClass);
+               this._showDatepicker(this._dialogInput[0]);
+               if ($.blockUI)
+                       $.blockUI(this.dpDiv);
+               $.data(this._dialogInput[0], PROP_NAME, inst);
+               return this;
+       },
+
+       /* Detach a datepicker from its control.
+          @param  target    element - the target input field or division or span */
+       _destroyDatepicker: function(target) {
+               var $target = $(target);
+               var inst = $.data(target, PROP_NAME);
+               if (!$target.hasClass(this.markerClassName)) {
+                       return;
+               }
+               var nodeName = target.nodeName.toLowerCase();
+               $.removeData(target, PROP_NAME);
+               if (nodeName == 'input') {
+                       inst.append.remove();
+                       inst.trigger.remove();
+                       $target.removeClass(this.markerClassName).
+                               unbind('focus', this._showDatepicker).
+                               unbind('keydown', this._doKeyDown).
+                               unbind('keypress', this._doKeyPress);
+               } else if (nodeName == 'div' || nodeName == 'span')
+                       $target.removeClass(this.markerClassName).empty();
+       },
+
+       /* Enable the date picker to a jQuery selection.
+          @param  target    element - the target input field or division or span */
+       _enableDatepicker: function(target) {
+               var $target = $(target);
+               var inst = $.data(target, PROP_NAME);
+               if (!$target.hasClass(this.markerClassName)) {
+                       return;
+               }
+               var nodeName = target.nodeName.toLowerCase();
+               if (nodeName == 'input') {
+                       target.disabled = false;
+                       inst.trigger.filter('button').
+                               each(function() { this.disabled = false; }).end().
+                               filter('img').css({opacity: '1.0', cursor: ''});
+               }
+               else if (nodeName == 'div' || nodeName == 'span') {
+                       var inline = $target.children('.' + this._inlineClass);
+                       inline.children().removeClass('ui-state-disabled');
+               }
+               this._disabledInputs = $.map(this._disabledInputs,
+                       function(value) { return (value == target ? null : value); }); // delete entry
+       },
+
+       /* Disable the date picker to a jQuery selection.
+          @param  target    element - the target input field or division or span */
+       _disableDatepicker: function(target) {
+               var $target = $(target);
+               var inst = $.data(target, PROP_NAME);
+               if (!$target.hasClass(this.markerClassName)) {
+                       return;
+               }
+               var nodeName = target.nodeName.toLowerCase();
+               if (nodeName == 'input') {
+                       target.disabled = true;
+                       inst.trigger.filter('button').
+                               each(function() { this.disabled = true; }).end().
+                               filter('img').css({opacity: '0.5', cursor: 'default'});
+               }
+               else if (nodeName == 'div' || nodeName == 'span') {
+                       var inline = $target.children('.' + this._inlineClass);
+                       inline.children().addClass('ui-state-disabled');
+               }
+               this._disabledInputs = $.map(this._disabledInputs,
+                       function(value) { return (value == target ? null : value); }); // delete entry
+               this._disabledInputs[this._disabledInputs.length] = target;
+       },
+
+       /* Is the first field in a jQuery collection disabled as a datepicker?
+          @param  target    element - the target input field or division or span
+          @return boolean - true if disabled, false if enabled */
+       _isDisabledDatepicker: function(target) {
+               if (!target) {
+                       return false;
+               }
+               for (var i = 0; i < this._disabledInputs.length; i++) {
+                       if (this._disabledInputs[i] == target)
+                               return true;
+               }
+               return false;
+       },
+
+       /* Retrieve the instance data for the target control.
+          @param  target  element - the target input field or division or span
+          @return  object - the associated instance data
+          @throws  error if a jQuery problem getting data */
+       _getInst: function(target) {
+               try {
+                       return $.data(target, PROP_NAME);
+               }
+               catch (err) {
+                       throw 'Missing instance data for this datepicker';
+               }
+       },
+
+       /* Update or retrieve the settings for a date picker attached to an input field or division.
+          @param  target  element - the target input field or division or span
+          @param  name    object - the new settings to update or
+                          string - the name of the setting to change or retrieve,
+                          when retrieving also 'all' for all instance settings or
+                          'defaults' for all global defaults
+          @param  value   any - the new value for the setting
+                          (omit if above is an object or to retrieve a value) */
+       _optionDatepicker: function(target, name, value) {
+               var inst = this._getInst(target);
+               if (arguments.length == 2 && typeof name == 'string') {
+                       return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
+                               (inst ? (name == 'all' ? $.extend({}, inst.settings) :
+                               this._get(inst, name)) : null));
+               }
+               var settings = name || {};
+               if (typeof name == 'string') {
+                       settings = {};
+                       settings[name] = value;
+               }
+               if (inst) {
+                       if (this._curInst == inst) {
+                               this._hideDatepicker(null);
+                       }
+                       var date = this._getDateDatepicker(target);
+                       extendRemove(inst.settings, settings);
+                       this._setDateDatepicker(target, date);
+                       this._updateDatepicker(inst);
+               }
+       },
+
+       // change method deprecated
+       _changeDatepicker: function(target, name, value) {
+               this._optionDatepicker(target, name, value);
+       },
+
+       /* Redraw the date picker attached to an input field or division.
+          @param  target  element - the target input field or division or span */
+       _refreshDatepicker: function(target) {
+               var inst = this._getInst(target);
+               if (inst) {
+                       this._updateDatepicker(inst);
+               }
+       },
+
+       /* Set the dates for a jQuery selection.
+          @param  target   element - the target input field or division or span
+          @param  date     Date - the new date
+          @param  endDate  Date - the new end date for a range (optional) */
+       _setDateDatepicker: function(target, date, endDate) {
+               var inst = this._getInst(target);
+               if (inst) {
+                       this._setDate(inst, date, endDate);
+                       this._updateDatepicker(inst);
+                       this._updateAlternate(inst);
+               }
+       },
+
+       /* Get the date(s) for the first entry in a jQuery selection.
+          @param  target  element - the target input field or division or span
+          @return Date - the current date or
+                  Date[2] - the current dates for a range */
+       _getDateDatepicker: function(target) {
+               var inst = this._getInst(target);
+               if (inst && !inst.inline)
+                       this._setDateFromField(inst);
+               return (inst ? this._getDate(inst) : null);
+       },
+
+       /* Handle keystrokes. */
+       _doKeyDown: function(event) {
+               var inst = $.datepicker._getInst(event.target);
+               var handled = true;
+               var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
+               inst._keyEvent = true;
+               if ($.datepicker._datepickerShowing)
+                       switch (event.keyCode) {
+                               case 9:  $.datepicker._hideDatepicker(null, '');
+                                               break; // hide on tab out
+                               case 13: var sel = $('td.' + $.datepicker._dayOverClass +
+                                                       ', td.' + $.datepicker._currentClass, inst.dpDiv);
+                                               if (sel[0])
+                                                       $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
+                                               else
+                                                       $.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration'));
+                                               return false; // don't submit the form
+                                               break; // select the value on enter
+                               case 27: $.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration'));
+                                               break; // hide on escape
+                               case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
+                                                       -$.datepicker._get(inst, 'stepBigMonths') :
+                                                       -$.datepicker._get(inst, 'stepMonths')), 'M');
+                                               break; // previous month/year on page up/+ ctrl
+                               case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
+                                                       +$.datepicker._get(inst, 'stepBigMonths') :
+                                                       +$.datepicker._get(inst, 'stepMonths')), 'M');
+                                               break; // next month/year on page down/+ ctrl
+                               case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
+                                               handled = event.ctrlKey || event.metaKey;
+                                               break; // clear on ctrl or command +end
+                               case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
+                                               handled = event.ctrlKey || event.metaKey;
+                                               break; // current on ctrl or command +home
+                               case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
+                                               handled = event.ctrlKey || event.metaKey;
+                                               // -1 day on ctrl or command +left
+                                               if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
+                                                                       -$.datepicker._get(inst, 'stepBigMonths') :
+                                                                       -$.datepicker._get(inst, 'stepMonths')), 'M');
+                                               // next month/year on alt +left on Mac
+                                               break;
+                               case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
+                                               handled = event.ctrlKey || event.metaKey;
+                                               break; // -1 week on ctrl or command +up
+                               case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
+                                               handled = event.ctrlKey || event.metaKey;
+                                               // +1 day on ctrl or command +right
+                                               if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
+                                                                       +$.datepicker._get(inst, 'stepBigMonths') :
+                                                                       +$.datepicker._get(inst, 'stepMonths')), 'M');
+                                               // next month/year on alt +right
+                                               break;
+                               case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
+                                               handled = event.ctrlKey || event.metaKey;
+                                               break; // +1 week on ctrl or command +down
+                               default: handled = false;
+                       }
+               else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
+                       $.datepicker._showDatepicker(this);
+               else {
+                       handled = false;
+               }
+               if (handled) {
+                       event.preventDefault();
+                       event.stopPropagation();
+               }
+       },
+
+       /* Filter entered characters - based on date format. */
+       _doKeyPress: function(event) {
+               var inst = $.datepicker._getInst(event.target);
+               if ($.datepicker._get(inst, 'constrainInput')) {
+                       var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
+                       var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
+                       return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
+               }
+       },
+
+       /* Pop-up the date picker for a given input field.
+          @param  input  element - the input field attached to the date picker or
+                         event - if triggered by focus */
+       _showDatepicker: function(input) {
+               input = input.target || input;
+               if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
+                       input = $('input', input.parentNode)[0];
+               if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
+                       return;
+               var inst = $.datepicker._getInst(input);
+               var beforeShow = $.datepicker._get(inst, 'beforeShow');
+               extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
+               $.datepicker._hideDatepicker(null, '');
+               $.datepicker._lastInput = input;
+               $.datepicker._setDateFromField(inst);
+               if ($.datepicker._inDialog) // hide cursor
+                       input.value = '';
+               if (!$.datepicker._pos) { // position below input
+                       $.datepicker._pos = $.datepicker._findPos(input);
+                       $.datepicker._pos[1] += input.offsetHeight; // add the height
+               }
+               var isFixed = false;
+               $(input).parents().each(function() {
+                       isFixed |= $(this).css('position') == 'fixed';
+                       return !isFixed;
+               });
+               if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
+                       $.datepicker._pos[0] -= document.documentElement.scrollLeft;
+                       $.datepicker._pos[1] -= document.documentElement.scrollTop;
+               }
+               var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
+               $.datepicker._pos = null;
+               inst.rangeStart = null;
+               // determine sizing offscreen
+               inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
+               $.datepicker._updateDatepicker(inst);
+               // fix width for dynamic number of date pickers
+               // and adjust position before showing
+               offset = $.datepicker._checkOffset(inst, offset, isFixed);
+               inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
+                       'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
+                       left: offset.left + 'px', top: offset.top + 'px'});
+               if (!inst.inline) {
+                       var showAnim = $.datepicker._get(inst, 'showAnim') || 'show';
+                       var duration = $.datepicker._get(inst, 'duration');
+                       var postProcess = function() {
+                               $.datepicker._datepickerShowing = true;
+                               if ($.browser.msie && parseInt($.browser.version,10) < 7) // fix IE < 7 select problems
+                                       $('iframe.ui-datepicker-cover').css({width: inst.dpDiv.width() + 4,
+                                               height: inst.dpDiv.height() + 4});
+                       };
+                       if ($.effects && $.effects[showAnim])
+                               inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
+                       else
+                               inst.dpDiv[showAnim](duration, postProcess);
+                       if (duration == '')
+                               postProcess();
+                       if (inst.input[0].type != 'hidden')
+                               inst.input[0].focus();
+                       $.datepicker._curInst = inst;
+               }
+       },
+
+       /* Generate the date picker content. */
+       _updateDatepicker: function(inst) {
+               var dims = {width: inst.dpDiv.width() + 4,
+                       height: inst.dpDiv.height() + 4};
+               var self = this;
+               inst.dpDiv.empty().append(this._generateHTML(inst))
+                       .find('iframe.ui-datepicker-cover').
+                               css({width: dims.width, height: dims.height})
+                       .end()
+                       .find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
+                               .bind('mouseout', function(){
+                                       $(this).removeClass('ui-state-hover');
+                                       if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
+                                       if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
+                               })
+                               .bind('mouseover', function(){
+                                       if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
+                                               $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
+                                               $(this).addClass('ui-state-hover');
+                                               if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
+                                               if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
+                                       }
+                               })
+                       .end()
+                       .find('.' + this._dayOverClass + ' a')
+                               .trigger('mouseover')
+                       .end();
+               var numMonths = this._getNumberOfMonths(inst);
+               var cols = numMonths[1];
+               var width = 17;
+               if (cols > 1) {
+                       inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
+               } else {
+                       inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
+               }
+               inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
+                       'Class']('ui-datepicker-multi');
+               inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
+                       'Class']('ui-datepicker-rtl');
+               if (inst.input && inst.input[0].type != 'hidden' && inst == $.datepicker._curInst)
+                       $(inst.input[0]).focus();
+       },
+
+       /* Check positioning to remain on screen. */
+       _checkOffset: function(inst, offset, isFixed) {
+               var dpWidth = inst.dpDiv.outerWidth();
+               var dpHeight = inst.dpDiv.outerHeight();
+               var inputWidth = inst.input ? inst.input.outerWidth() : 0;
+               var inputHeight = inst.input ? inst.input.outerHeight() : 0;
+               var viewWidth = (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) + $(document).scrollLeft();
+               var viewHeight = (window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight) + $(document).scrollTop();
+
+               offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
+               offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
+               offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
+
+               // now check if datepicker is showing outside window viewport - move to a better place if so.
+               offset.left -= (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? Math.abs(offset.left + dpWidth - viewWidth) : 0;
+               offset.top -= (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? Math.abs(offset.top + dpHeight + inputHeight*2 - viewHeight) : 0;
+
+               return offset;
+       },
+
+       /* Find an object's position on the screen. */
+       _findPos: function(obj) {
+        while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
+            obj = obj.nextSibling;
+        }
+        var position = $(obj).offset();
+           return [position.left, position.top];
+       },
+
+       /* Hide the date picker from view.
+          @param  input  element - the input field attached to the date picker
+          @param  duration  string - the duration over which to close the date picker */
+       _hideDatepicker: function(input, duration) {
+               var inst = this._curInst;
+               if (!inst || (input && inst != $.data(input, PROP_NAME)))
+                       return;
+               if (inst.stayOpen)
+                       this._selectDate('#' + inst.id, this._formatDate(inst,
+                               inst.currentDay, inst.currentMonth, inst.currentYear));
+               inst.stayOpen = false;
+               if (this._datepickerShowing) {
+                       duration = (duration != null ? duration : this._get(inst, 'duration'));
+                       var showAnim = this._get(inst, 'showAnim');
+                       var postProcess = function() {
+                               $.datepicker._tidyDialog(inst);
+                       };
+                       if (duration != '' && $.effects && $.effects[showAnim])
+                               inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'),
+                                       duration, postProcess);
+                       else
+                               inst.dpDiv[(duration == '' ? 'hide' : (showAnim == 'slideDown' ? 'slideUp' :
+                                       (showAnim == 'fadeIn' ? 'fadeOut' : 'hide')))](duration, postProcess);
+                       if (duration == '')
+                               this._tidyDialog(inst);
+                       var onClose = this._get(inst, 'onClose');
+                       if (onClose)
+                               onClose.apply((inst.input ? inst.input[0] : null),
+                                       [(inst.input ? inst.input.val() : ''), inst]);  // trigger custom callback
+                       this._datepickerShowing = false;
+                       this._lastInput = null;
+                       if (this._inDialog) {
+                               this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
+                               if ($.blockUI) {
+                                       $.unblockUI();
+                                       $('body').append(this.dpDiv);
+                               }
+                       }
+                       this._inDialog = false;
+               }
+               this._curInst = null;
+       },
+
+       /* Tidy up after a dialog display. */
+       _tidyDialog: function(inst) {
+               inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
+       },
+
+       /* Close date picker if clicked elsewhere. */
+       _checkExternalClick: function(event) {
+               if (!$.datepicker._curInst)
+                       return;
+               var $target = $(event.target);
+               if (($target.parents('#' + $.datepicker._mainDivId).length == 0) &&
+                               !$target.hasClass($.datepicker.markerClassName) &&
+                               !$target.hasClass($.datepicker._triggerClass) &&
+                               $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
+                       $.datepicker._hideDatepicker(null, '');
+       },
+
+       /* Adjust one of the date sub-fields. */
+       _adjustDate: function(id, offset, period) {
+               var target = $(id);
+               var inst = this._getInst(target[0]);
+               if (this._isDisabledDatepicker(target[0])) {
+                       return;
+               }
+               this._adjustInstDate(inst, offset +
+                       (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
+                       period);
+               this._updateDatepicker(inst);
+       },
+
+       /* Action for current link. */
+       _gotoToday: function(id) {
+               var target = $(id);
+               var inst = this._getInst(target[0]);
+               if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
+                       inst.selectedDay = inst.currentDay;
+                       inst.drawMonth = inst.selectedMonth = inst.currentMonth;
+                       inst.drawYear = inst.selectedYear = inst.currentYear;
+               }
+               else {
+               var date = new Date();
+               inst.selectedDay = date.getDate();
+               inst.drawMonth = inst.selectedMonth = date.getMonth();
+               inst.drawYear = inst.selectedYear = date.getFullYear();
+               }
+               this._notifyChange(inst);
+               this._adjustDate(target);
+       },
+
+       /* Action for selecting a new month/year. */
+       _selectMonthYear: function(id, select, period) {
+               var target = $(id);
+               var inst = this._getInst(target[0]);
+               inst._selectingMonthYear = false;
+               inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
+               inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
+                       parseInt(select.options[select.selectedIndex].value,10);
+               this._notifyChange(inst);
+               this._adjustDate(target);
+       },
+
+       /* Restore input focus after not changing month/year. */
+       _clickMonthYear: function(id) {
+               var target = $(id);
+               var inst = this._getInst(target[0]);
+               if (inst.input && inst._selectingMonthYear && !$.browser.msie)
+                       inst.input[0].focus();
+               inst._selectingMonthYear = !inst._selectingMonthYear;
+       },
+
+       /* Action for selecting a day. */
+       _selectDay: function(id, month, year, td) {
+               var target = $(id);
+               if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
+                       return;
+               }
+               var inst = this._getInst(target[0]);
+               inst.selectedDay = inst.currentDay = $('a', td).html();
+               inst.selectedMonth = inst.currentMonth = month;
+               inst.selectedYear = inst.currentYear = year;
+               if (inst.stayOpen) {
+                       inst.endDay = inst.endMonth = inst.endYear = null;
+               }
+               this._selectDate(id, this._formatDate(inst,
+                       inst.currentDay, inst.currentMonth, inst.currentYear));
+               if (inst.stayOpen) {
+                       inst.rangeStart = this._daylightSavingAdjust(
+                               new Date(inst.currentYear, inst.currentMonth, inst.currentDay));
+                       this._updateDatepicker(inst);
+               }
+       },
+
+       /* Erase the input field and hide the date picker. */
+       _clearDate: function(id) {
+               var target = $(id);
+               var inst = this._getInst(target[0]);
+               inst.stayOpen = false;
+               inst.endDay = inst.endMonth = inst.endYear = inst.rangeStart = null;
+               this._selectDate(target, '');
+       },
+
+       /* Update the input field with the selected date. */
+       _selectDate: function(id, dateStr) {
+               var target = $(id);
+               var inst = this._getInst(target[0]);
+               dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
+               if (inst.input)
+                       inst.input.val(dateStr);
+               this._updateAlternate(inst);
+               var onSelect = this._get(inst, 'onSelect');
+               if (onSelect)
+                       onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
+               else if (inst.input)
+                       inst.input.trigger('change'); // fire the change event
+               if (inst.inline)
+                       this._updateDatepicker(inst);
+               else if (!inst.stayOpen) {
+                       this._hideDatepicker(null, this._get(inst, 'duration'));
+                       this._lastInput = inst.input[0];
+                       if (typeof(inst.input[0]) != 'object')
+                               inst.input[0].focus(); // restore focus
+                       this._lastInput = null;
+               }
+       },
+
+       /* Update any alternate field to synchronise with the main field. */
+       _updateAlternate: function(inst) {
+               var altField = this._get(inst, 'altField');
+               if (altField) { // update alternate field too
+                       var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
+                       var date = this._getDate(inst);
+                       dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
+                       $(altField).each(function() { $(this).val(dateStr); });
+               }
+       },
+
+       /* Set as beforeShowDay function to prevent selection of weekends.
+          @param  date  Date - the date to customise
+          @return [boolean, string] - is this date selectable?, what is its CSS class? */
+       noWeekends: function(date) {
+               var day = date.getDay();
+               return [(day > 0 && day < 6), ''];
+       },
+
+       /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
+          @param  date  Date - the date to get the week for
+          @return  number - the number of the week within the year that contains this date */
+       iso8601Week: function(date) {
+               var checkDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
+               var firstMon = new Date(checkDate.getFullYear(), 1 - 1, 4); // First week always contains 4 Jan
+               var firstDay = firstMon.getDay() || 7; // Day of week: Mon = 1, ..., Sun = 7
+               firstMon.setDate(firstMon.getDate() + 1 - firstDay); // Preceding Monday
+               if (firstDay < 4 && checkDate < firstMon) { // Adjust first three days in year if necessary
+                       checkDate.setDate(checkDate.getDate() - 3); // Generate for previous year
+                       return $.datepicker.iso8601Week(checkDate);
+               } else if (checkDate > new Date(checkDate.getFullYear(), 12 - 1, 28)) { // Check last three days in year
+                       firstDay = new Date(checkDate.getFullYear() + 1, 1 - 1, 4).getDay() || 7;
+                       if (firstDay > 4 && (checkDate.getDay() || 7) < firstDay - 3) { // Adjust if necessary
+                               return 1;
+                       }
+               }
+               return Math.floor(((checkDate - firstMon) / 86400000) / 7) + 1; // Weeks to given date
+       },
+
+       /* Parse a string value into a date object.
+          See formatDate below for the possible formats.
+
+          @param  format    string - the expected format of the date
+          @param  value     string - the date in the above format
+          @param  settings  Object - attributes include:
+                            shortYearCutoff  number - the cutoff year for determining the century (optional)
+                            dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
+                            dayNames         string[7] - names of the days from Sunday (optional)
+                            monthNamesShort  string[12] - abbreviated names of the months (optional)
+                            monthNames       string[12] - names of the months (optional)
+          @return  Date - the extracted date value or null if value is blank */
+       parseDate: function (format, value, settings) {
+               if (format == null || value == null)
+                       throw 'Invalid arguments';
+               value = (typeof value == 'object' ? value.toString() : value + '');
+               if (value == '')
+                       return null;
+               var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
+               var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
+               var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
+               var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
+               var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
+               var year = -1;
+               var month = -1;
+               var day = -1;
+               var doy = -1;
+               var literal = false;
+               // Check whether a format character is doubled
+               var lookAhead = function(match) {
+                       var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
+                       if (matches)
+                               iFormat++;
+                       return matches;
+               };
+               // Extract a number from the string value
+               var getNumber = function(match) {
+                       lookAhead(match);
+                       var origSize = (match == '@' ? 14 : (match == 'y' ? 4 : (match == 'o' ? 3 : 2)));
+                       var size = origSize;
+                       var num = 0;
+                       while (size > 0 && iValue < value.length &&
+                                       value.charAt(iValue) >= '0' && value.charAt(iValue) <= '9') {
+                               num = num * 10 + parseInt(value.charAt(iValue++),10);
+                               size--;
+                       }
+                       if (size == origSize)
+                               throw 'Missing number at position ' + iValue;
+                       return num;
+               };
+               // Extract a name from the string value and convert to an index
+               var getName = function(match, shortNames, longNames) {
+                       var names = (lookAhead(match) ? longNames : shortNames);
+                       var size = 0;
+                       for (var j = 0; j < names.length; j++)
+                               size = Math.max(size, names[j].length);
+                       var name = '';
+                       var iInit = iValue;
+                       while (size > 0 && iValue < value.length) {
+                               name += value.charAt(iValue++);
+                               for (var i = 0; i < names.length; i++)
+                                       if (name == names[i])
+                                               return i + 1;
+                               size--;
+                       }
+                       throw 'Unknown name at position ' + iInit;
+               };
+               // Confirm that a literal character matches the string value
+               var checkLiteral = function() {
+                       if (value.charAt(iValue) != format.charAt(iFormat))
+                               throw 'Unexpected literal at position ' + iValue;
+                       iValue++;
+               };
+               var iValue = 0;
+               for (var iFormat = 0; iFormat < format.length; iFormat++) {
+                       if (literal)
+                               if (format.charAt(iFormat) == "'" && !lookAhead("'"))
+                                       literal = false;
+                               else
+                                       checkLiteral();
+                       else
+                               switch (format.charAt(iFormat)) {
+                                       case 'd':
+                                               day = getNumber('d');
+                                               break;
+                                       case 'D':
+                                               getName('D', dayNamesShort, dayNames);
+                                               break;
+                                       case 'o':
+                                               doy = getNumber('o');
+                                               break;
+                                       case 'm':
+                                               month = getNumber('m');
+                                               break;
+                                       case 'M':
+                                               month = getName('M', monthNamesShort, monthNames);
+                                               break;
+                                       case 'y':
+                                               year = getNumber('y');
+                                               break;
+                                       case '@':
+                                               var date = new Date(getNumber('@'));
+                                               year = date.getFullYear();
+                                               month = date.getMonth() + 1;
+                                               day = date.getDate();
+                                               break;
+                                       case "'":
+                                               if (lookAhead("'"))
+                                                       checkLiteral();
+                                               else
+                                                       literal = true;
+                                               break;
+                                       default:
+                                               checkLiteral();
+                               }
+               }
+               if (year == -1)
+                       year = new Date().getFullYear();
+               else if (year < 100)
+                       year += new Date().getFullYear() - new Date().getFullYear() % 100 +
+                               (year <= shortYearCutoff ? 0 : -100);
+               if (doy > -1) {
+                       month = 1;
+                       day = doy;
+                       do {
+                               var dim = this._getDaysInMonth(year, month - 1);
+                               if (day <= dim)
+                                       break;
+                               month++;
+                               day -= dim;
+                       } while (true);
+               }
+               var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
+               if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
+                       throw 'Invalid date'; // E.g. 31/02/*
+               return date;
+       },
+
+       /* Standard date formats. */
+       ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
+       COOKIE: 'D, dd M yy',
+       ISO_8601: 'yy-mm-dd',
+       RFC_822: 'D, d M y',
+       RFC_850: 'DD, dd-M-y',
+       RFC_1036: 'D, d M y',
+       RFC_1123: 'D, d M yy',
+       RFC_2822: 'D, d M yy',
+       RSS: 'D, d M y', // RFC 822
+       TIMESTAMP: '@',
+       W3C: 'yy-mm-dd', // ISO 8601
+
+       /* Format a date object into a string value.
+          The format can be combinations of the following:
+          d  - day of month (no leading zero)
+          dd - day of month (two digit)
+          o  - day of year (no leading zeros)
+          oo - day of year (three digit)
+          D  - day name short
+          DD - day name long
+          m  - month of year (no leading zero)
+          mm - month of year (two digit)
+          M  - month name short
+          MM - month name long
+          y  - year (two digit)
+          yy - year (four digit)
+          @ - Unix timestamp (ms since 01/01/1970)
+          '...' - literal text
+          '' - single quote
+
+          @param  format    string - the desired format of the date
+          @param  date      Date - the date value to format
+          @param  settings  Object - attributes include:
+                            dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
+                            dayNames         string[7] - names of the days from Sunday (optional)
+                            monthNamesShort  string[12] - abbreviated names of the months (optional)
+                            monthNames       string[12] - names of the months (optional)
+          @return  string - the date in the above format */
+       formatDate: function (format, date, settings) {
+               if (!date)
+                       return '';
+               var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
+               var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
+               var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
+               var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
+               // Check whether a format character is doubled
+               var lookAhead = function(match) {
+                       var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
+                       if (matches)
+                               iFormat++;
+                       return matches;
+               };
+               // Format a number, with leading zero if necessary
+               var formatNumber = function(match, value, len) {
+                       var num = '' + value;
+                       if (lookAhead(match))
+                               while (num.length < len)
+                                       num = '0' + num;
+                       return num;
+               };
+               // Format a name, short or long as requested
+               var formatName = function(match, value, shortNames, longNames) {
+                       return (lookAhead(match) ? longNames[value] : shortNames[value]);
+               };
+               var output = '';
+               var literal = false;
+               if (date)
+                       for (var iFormat = 0; iFormat < format.length; iFormat++) {
+                               if (literal)
+                                       if (format.charAt(iFormat) == "'" && !lookAhead("'"))
+                                               literal = false;
+                                       else
+                                               output += format.charAt(iFormat);
+                               else
+                                       switch (format.charAt(iFormat)) {
+                                               case 'd':
+                                                       output += formatNumber('d', date.getDate(), 2);
+                                                       break;
+                                               case 'D':
+                                                       output += formatName('D', date.getDay(), dayNamesShort, dayNames);
+                                                       break;
+                                               case 'o':
+                                                       var doy = date.getDate();
+                                                       for (var m = date.getMonth() - 1; m >= 0; m--)
+                                                               doy += this._getDaysInMonth(date.getFullYear(), m);
+                                                       output += formatNumber('o', doy, 3);
+                                                       break;
+                                               case 'm':
+                                                       output += formatNumber('m', date.getMonth() + 1, 2);
+                                                       break;
+                                               case 'M':
+                                                       output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
+                                                       break;
+                                               case 'y':
+                                                       output += (lookAhead('y') ? date.getFullYear() :
+                                                               (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
+                                                       break;
+                                               case '@':
+                                                       output += date.getTime();
+                                                       break;
+                                               case "'":
+                                                       if (lookAhead("'"))
+                                                               output += "'";
+                                                       else
+                                                               literal = true;
+                                                       break;
+                                               default:
+                                                       output += format.charAt(iFormat);
+                                       }
+                       }
+               return output;
+       },
+
+       /* Extract all possible characters from the date format. */
+       _possibleChars: function (format) {
+               var chars = '';
+               var literal = false;
+               for (var iFormat = 0; iFormat < format.length; iFormat++)
+                       if (literal)
+                               if (format.charAt(iFormat) == "'" && !lookAhead("'"))
+                                       literal = false;
+                               else
+                                       chars += format.charAt(iFormat);
+                       else
+                               switch (format.charAt(iFormat)) {
+                                       case 'd': case 'm': case 'y': case '@':
+                                               chars += '0123456789';
+                                               break;
+                                       case 'D': case 'M':
+                                               return null; // Accept anything
+                                       case "'":
+                                               if (lookAhead("'"))
+                                                       chars += "'";
+                                               else
+                                                       literal = true;
+                                               break;
+                                       default:
+                                               chars += format.charAt(iFormat);
+                               }
+               return chars;
+       },
+
+       /* Get a setting value, defaulting if necessary. */
+       _get: function(inst, name) {
+               return inst.settings[name] !== undefined ?
+                       inst.settings[name] : this._defaults[name];
+       },
+
+       /* Parse existing date and initialise date picker. */
+       _setDateFromField: function(inst) {
+               var dateFormat = this._get(inst, 'dateFormat');
+               var dates = inst.input ? inst.input.val() : null;
+               inst.endDay = inst.endMonth = inst.endYear = null;
+               var date = defaultDate = this._getDefaultDate(inst);
+               var settings = this._getFormatConfig(inst);
+               try {
+                       date = this.parseDate(dateFormat, dates, settings) || defaultDate;
+               } catch (event) {
+                       this.log(event);
+                       date = defaultDate;
+               }
+               inst.selectedDay = date.getDate();
+               inst.drawMonth = inst.selectedMonth = date.getMonth();
+               inst.drawYear = inst.selectedYear = date.getFullYear();
+               inst.currentDay = (dates ? date.getDate() : 0);
+               inst.currentMonth = (dates ? date.getMonth() : 0);
+               inst.currentYear = (dates ? date.getFullYear() : 0);
+               this._adjustInstDate(inst);
+       },
+
+       /* Retrieve the default date shown on opening. */
+       _getDefaultDate: function(inst) {
+               var date = this._determineDate(this._get(inst, 'defaultDate'), new Date());
+               var minDate = this._getMinMaxDate(inst, 'min', true);
+               var maxDate = this._getMinMaxDate(inst, 'max');
+               date = (minDate && date < minDate ? minDate : date);
+               date = (maxDate && date > maxDate ? maxDate : date);
+               return date;
+       },
+
+       /* A date may be specified as an exact value or a relative one. */
+       _determineDate: function(date, defaultDate) {
+               var offsetNumeric = function(offset) {
+                       var date = new Date();
+                       date.setDate(date.getDate() + offset);
+                       return date;
+               };
+               var offsetString = function(offset, getDaysInMonth) {
+                       var date = new Date();
+                       var year = date.getFullYear();
+                       var month = date.getMonth();
+                       var day = date.getDate();
+                       var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
+                       var matches = pattern.exec(offset);
+                       while (matches) {
+                               switch (matches[2] || 'd') {
+                                       case 'd' : case 'D' :
+                                               day += parseInt(matches[1],10); break;
+                                       case 'w' : case 'W' :
+                                               day += parseInt(matches[1],10) * 7; break;
+                                       case 'm' : case 'M' :
+                                               month += parseInt(matches[1],10);
+                                               day = Math.min(day, getDaysInMonth(year, month));
+                                               break;
+                                       case 'y': case 'Y' :
+                                               year += parseInt(matches[1],10);
+                                               day = Math.min(day, getDaysInMonth(year, month));
+                                               break;
+                               }
+                               matches = pattern.exec(offset);
+                       }
+                       return new Date(year, month, day);
+               };
+               date = (date == null ? defaultDate :
+                       (typeof date == 'string' ? offsetString(date, this._getDaysInMonth) :
+                       (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
+               date = (date && date.toString() == 'Invalid Date' ? defaultDate : date);
+               if (date) {
+                       date.setHours(0);
+                       date.setMinutes(0);
+                       date.setSeconds(0);
+                       date.setMilliseconds(0);
+               }
+               return this._daylightSavingAdjust(date);
+       },
+
+       /* Handle switch to/from daylight saving.
+          Hours may be non-zero on daylight saving cut-over:
+          > 12 when midnight changeover, but then cannot generate
+          midnight datetime, so jump to 1AM, otherwise reset.
+          @param  date  (Date) the date to check
+          @return  (Date) the corrected date */
+       _daylightSavingAdjust: function(date) {
+               if (!date) return null;
+               date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
+               return date;
+       },
+
+       /* Set the date(s) directly. */
+       _setDate: function(inst, date, endDate) {
+               var clear = !(date);
+               var origMonth = inst.selectedMonth;
+               var origYear = inst.selectedYear;
+               date = this._determineDate(date, new Date());
+               inst.selectedDay = inst.currentDay = date.getDate();
+               inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
+               inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
+               if (origMonth != inst.selectedMonth || origYear != inst.selectedYear)
+                       this._notifyChange(inst);
+               this._adjustInstDate(inst);
+               if (inst.input) {
+                       inst.input.val(clear ? '' : this._formatDate(inst));
+               }
+       },
+
+       /* Retrieve the date(s) directly. */
+       _getDate: function(inst) {
+               var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
+                       this._daylightSavingAdjust(new Date(
+                       inst.currentYear, inst.currentMonth, inst.currentDay)));
+                       return startDate;
+       },
+
+       /* Generate the HTML for the current state of the date picker. */
+       _generateHTML: function(inst) {
+               var today = new Date();
+               today = this._daylightSavingAdjust(
+                       new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
+               var isRTL = this._get(inst, 'isRTL');
+               var showButtonPanel = this._get(inst, 'showButtonPanel');
+               var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
+               var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
+               var numMonths = this._getNumberOfMonths(inst);
+               var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
+               var stepMonths = this._get(inst, 'stepMonths');
+               var stepBigMonths = this._get(inst, 'stepBigMonths');
+               var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
+               var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
+                       new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
+               var minDate = this._getMinMaxDate(inst, 'min', true);
+               var maxDate = this._getMinMaxDate(inst, 'max');
+               var drawMonth = inst.drawMonth - showCurrentAtPos;
+               var drawYear = inst.drawYear;
+               if (drawMonth < 0) {
+                       drawMonth += 12;
+                       drawYear--;
+               }
+               if (maxDate) {
+                       var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
+                               maxDate.getMonth() - numMonths[1] + 1, maxDate.getDate()));
+                       maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
+                       while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
+                               drawMonth--;
+                               if (drawMonth < 0) {
+                                       drawMonth = 11;
+                                       drawYear--;
+                               }
+                       }
+               }
+               inst.drawMonth = drawMonth;
+               inst.drawYear = drawYear;
+               var prevText = this._get(inst, 'prevText');
+               prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
+                       this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
+                       this._getFormatConfig(inst)));
+               var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
+                       '<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
+                       ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
+                       (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
+               var nextText = this._get(inst, 'nextText');
+               nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
+                       this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
+                       this._getFormatConfig(inst)));
+               var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
+                       '<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
+                       ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
+                       (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
+               var currentText = this._get(inst, 'currentText');
+               var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
+               currentText = (!navigationAsDateFormat ? currentText :
+                       this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
+               var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
+               var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
+                       (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery.datepicker._gotoToday(\'#' + inst.id + '\');"' +
+                       '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
+               var firstDay = parseInt(this._get(inst, 'firstDay'),10);
+               firstDay = (isNaN(firstDay) ? 0 : firstDay);
+               var dayNames = this._get(inst, 'dayNames');
+               var dayNamesShort = this._get(inst, 'dayNamesShort');
+               var dayNamesMin = this._get(inst, 'dayNamesMin');
+               var monthNames = this._get(inst, 'monthNames');
+               var monthNamesShort = this._get(inst, 'monthNamesShort');
+               var beforeShowDay = this._get(inst, 'beforeShowDay');
+               var showOtherMonths = this._get(inst, 'showOtherMonths');
+               var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
+               var endDate = inst.endDay ? this._daylightSavingAdjust(
+                       new Date(inst.endYear, inst.endMonth, inst.endDay)) : currentDate;
+               var defaultDate = this._getDefaultDate(inst);
+               var html = '';
+               for (var row = 0; row < numMonths[0]; row++) {
+                       var group = '';
+                       for (var col = 0; col < numMonths[1]; col++) {
+                               var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
+                               var cornerClass = ' ui-corner-all';
+                               var calender = '';
+                               if (isMultiMonth) {
+                                       calender += '<div class="ui-datepicker-group ui-datepicker-group-';
+                                       switch (col) {
+                                               case 0: calender += 'first'; cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
+                                               case numMonths[1]-1: calender += 'last'; cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
+                                               default: calender += 'middle'; cornerClass = ''; break;
+                                       }
+                                       calender += '">';
+                               }
+                               calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
+                                       (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
+                                       (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
+                                       this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
+                                       selectedDate, row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
+                                       '</div><table class="ui-datepicker-calendar"><thead>' +
+                                       '<tr>';
+                               var thead = '';
+                               for (var dow = 0; dow < 7; dow++) { // days of the week
+                                       var day = (dow + firstDay) % 7;
+                                       thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
+                                               '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
+                               }
+                               calender += thead + '</tr></thead><tbody>';
+                               var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
+                               if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
+                                       inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
+                               var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
+                               var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
+                               var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
+                               for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
+                                       calender += '<tr>';
+                                       var tbody = '';
+                                       for (var dow = 0; dow < 7; dow++) { // create date picker days
+                                               var daySettings = (beforeShowDay ?
+                                                       beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
+                                               var otherMonth = (printDate.getMonth() != drawMonth);
+                                               var unselectable = otherMonth || !daySettings[0] ||
+                                                       (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
+                                               tbody += '<td class="' +
+                                                       ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
+                                                       (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
+                                                       ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
+                                                       (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
+                                                       // or defaultDate is current printedDate and defaultDate is selectedDate
+                                                       ' ' + this._dayOverClass : '') + // highlight selected day
+                                                       (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days
+                                                       (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
+                                                       (printDate.getTime() >= currentDate.getTime() && printDate.getTime() <= endDate.getTime() ? // in current range
+                                                       ' ' + this._currentClass : '') + // highlight selected day
+                                                       (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
+                                                       ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
+                                                       (unselectable ? '' : ' onclick="DP_jQuery.datepicker._selectDay(\'#' +
+                                                       inst.id + '\',' + drawMonth + ',' + drawYear + ', this);return false;"') + '>' + // actions
+                                                       (otherMonth ? (showOtherMonths ? printDate.getDate() : '&#xa0;') : // display for other months
+                                                       (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
+                                                       (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
+                                                       (printDate.getTime() >= currentDate.getTime() && printDate.getTime() <= endDate.getTime() ? // in current range
+                                                       ' ui-state-active' : '') + // highlight selected day
+                                                       '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display for this month
+                                               printDate.setDate(printDate.getDate() + 1);
+                                               printDate = this._daylightSavingAdjust(printDate);
+                                       }
+                                       calender += tbody + '</tr>';
+                               }
+                               drawMonth++;
+                               if (drawMonth > 11) {
+                                       drawMonth = 0;
+                                       drawYear++;
+                               }
+                               calender += '</tbody></table>' + (isMultiMonth ? '</div>' + 
+                                                       ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
+                               group += calender;
+                       }
+                       html += group;
+               }
+               html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
+                       '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
+               inst._keyEvent = false;
+               return html;
+       },
+
+       /* Generate the month and year header. */
+       _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
+                       selectedDate, secondary, monthNames, monthNamesShort) {
+               minDate = (inst.rangeStart && minDate && selectedDate < minDate ? selectedDate : minDate);
+               var changeMonth = this._get(inst, 'changeMonth');
+               var changeYear = this._get(inst, 'changeYear');
+               var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
+               var html = '<div class="ui-datepicker-title">';
+               var monthHtml = '';
+               // month selection
+               if (secondary || !changeMonth)
+                       monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span> ';
+               else {
+                       var inMinYear = (minDate && minDate.getFullYear() == drawYear);
+                       var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
+                       monthHtml += '<select class="ui-datepicker-month" ' +
+                               'onchange="DP_jQuery.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
+                               'onclick="DP_jQuery.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
+                               '>';
+                       for (var month = 0; month < 12; month++) {
+                               if ((!inMinYear || month >= minDate.getMonth()) &&
+                                               (!inMaxYear || month <= maxDate.getMonth()))
+                                       monthHtml += '<option value="' + month + '"' +
+                                               (month == drawMonth ? ' selected="selected"' : '') +
+                                               '>' + monthNamesShort[month] + '</option>';
+                       }
+                       monthHtml += '</select>';
+               }
+               if (!showMonthAfterYear)
+                       html += monthHtml + ((secondary || changeMonth || changeYear) && (!(changeMonth && changeYear)) ? '&#xa0;' : '');
+               // year selection
+               if (secondary || !changeYear)
+                       html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
+               else {
+                       // determine range of years to display
+                       var years = this._get(inst, 'yearRange').split(':');
+                       var year = 0;
+                       var endYear = 0;
+                       if (years.length != 2) {
+                               year = drawYear - 10;
+                               endYear = drawYear + 10;
+                       } else if (years[0].charAt(0) == '+' || years[0].charAt(0) == '-') {
+                               year = drawYear + parseInt(years[0], 10);
+                               endYear = drawYear + parseInt(years[1], 10);
+                       } else {
+                               year = parseInt(years[0], 10);
+                               endYear = parseInt(years[1], 10);
+                       }
+                       year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
+                       endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
+                       html += '<select class="ui-datepicker-year" ' +
+                               'onchange="DP_jQuery.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
+                               'onclick="DP_jQuery.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
+                               '>';
+                       for (; year <= endYear; year++) {
+                               html += '<option value="' + year + '"' +
+                                       (year == drawYear ? ' selected="selected"' : '') +
+                                       '>' + year + '</option>';
+                       }
+                       html += '</select>';
+               }
+               if (showMonthAfterYear)
+                       html += (secondary || changeMonth || changeYear ? '&#xa0;' : '') + monthHtml;
+               html += '</div>'; // Close datepicker_header
+               return html;
+       },
+
+       /* Adjust one of the date sub-fields. */
+       _adjustInstDate: function(inst, offset, period) {
+               var year = inst.drawYear + (period == 'Y' ? offset : 0);
+               var month = inst.drawMonth + (period == 'M' ? offset : 0);
+               var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
+                       (period == 'D' ? offset : 0);
+               var date = this._daylightSavingAdjust(new Date(year, month, day));
+               // ensure it is within the bounds set
+               var minDate = this._getMinMaxDate(inst, 'min', true);
+               var maxDate = this._getMinMaxDate(inst, 'max');
+               date = (minDate && date < minDate ? minDate : date);
+               date = (maxDate && date > maxDate ? maxDate : date);
+               inst.selectedDay = date.getDate();
+               inst.drawMonth = inst.selectedMonth = date.getMonth();
+               inst.drawYear = inst.selectedYear = date.getFullYear();
+               if (period == 'M' || period == 'Y')
+                       this._notifyChange(inst);
+       },
+
+       /* Notify change of month/year. */
+       _notifyChange: function(inst) {
+               var onChange = this._get(inst, 'onChangeMonthYear');
+               if (onChange)
+                       onChange.apply((inst.input ? inst.input[0] : null),
+                               [inst.selectedYear, inst.selectedMonth + 1, inst]);
+       },
+
+       /* Determine the number of months to show. */
+       _getNumberOfMonths: function(inst) {
+               var numMonths = this._get(inst, 'numberOfMonths');
+               return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
+       },
+
+       /* Determine the current maximum date - ensure no time components are set - may be overridden for a range. */
+       _getMinMaxDate: function(inst, minMax, checkRange) {
+               var date = this._determineDate(this._get(inst, minMax + 'Date'), null);
+               return (!checkRange || !inst.rangeStart ? date :
+                       (!date || inst.rangeStart > date ? inst.rangeStart : date));
+       },
+
+       /* Find the number of days in a given month. */
+       _getDaysInMonth: function(year, month) {
+               return 32 - new Date(year, month, 32).getDate();
+       },
+
+       /* Find the day of the week of the first of a month. */
+       _getFirstDayOfMonth: function(year, month) {
+               return new Date(year, month, 1).getDay();
+       },
+
+       /* Determines if we should allow a "next/prev" month display change. */
+       _canAdjustMonth: function(inst, offset, curYear, curMonth) {
+               var numMonths = this._getNumberOfMonths(inst);
+               var date = this._daylightSavingAdjust(new Date(
+                       curYear, curMonth + (offset < 0 ? offset : numMonths[1]), 1));
+               if (offset < 0)
+                       date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
+               return this._isInRange(inst, date);
+       },
+
+       /* Is the given date in the accepted range? */
+       _isInRange: function(inst, date) {
+               // during range selection, use minimum of selected date and range start
+               var newMinDate = (!inst.rangeStart ? null : this._daylightSavingAdjust(
+                       new Date(inst.selectedYear, inst.selectedMonth, inst.selectedDay)));
+               newMinDate = (newMinDate && inst.rangeStart < newMinDate ? inst.rangeStart : newMinDate);
+               var minDate = newMinDate || this._getMinMaxDate(inst, 'min');
+               var maxDate = this._getMinMaxDate(inst, 'max');
+               return ((!minDate || date >= minDate) && (!maxDate || date <= maxDate));
+       },
+
+       /* Provide the configuration settings for formatting/parsing. */
+       _getFormatConfig: function(inst) {
+               var shortYearCutoff = this._get(inst, 'shortYearCutoff');
+               shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
+                       new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
+               return {shortYearCutoff: shortYearCutoff,
+                       dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
+                       monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
+       },
+
+       /* Format the given date for display. */
+       _formatDate: function(inst, day, month, year) {
+               if (!day) {
+                       inst.currentDay = inst.selectedDay;
+                       inst.currentMonth = inst.selectedMonth;
+                       inst.currentYear = inst.selectedYear;
+               }
+               var date = (day ? (typeof day == 'object' ? day :
+                       this._daylightSavingAdjust(new Date(year, month, day))) :
+                       this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
+               return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
+       }
+});
+
+/* jQuery extend now ignores nulls! */
+function extendRemove(target, props) {
+       $.extend(target, props);
+       for (var name in props)
+               if (props[name] == null || props[name] == undefined)
+                       target[name] = props[name];
+       return target;
+};
+
+/* Determine whether an object is an array. */
+function isArray(a) {
+       return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
+               (a.constructor && a.constructor.toString().match(/\Array\(\)/))));
+};
+
+/* Invoke the datepicker functionality.
+   @param  options  string - a command, optionally followed by additional parameters or
+                    Object - settings for attaching new datepicker functionality
+   @return  jQuery object */
+$.fn.datepicker = function(options){
+
+       /* Initialise the date picker. */
+       if (!$.datepicker.initialized) {
+               $(document).mousedown($.datepicker._checkExternalClick).
+                       find('body').append($.datepicker.dpDiv);
+               $.datepicker.initialized = true;
+       }
+
+       var otherArgs = Array.prototype.slice.call(arguments, 1);
+       if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate'))
+               return $.datepicker['_' + options + 'Datepicker'].
+                       apply($.datepicker, [this[0]].concat(otherArgs));
+       if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
+               return $.datepicker['_' + options + 'Datepicker'].
+                       apply($.datepicker, [this[0]].concat(otherArgs));
+       return this.each(function() {
+               typeof options == 'string' ?
+                       $.datepicker['_' + options + 'Datepicker'].
+                               apply($.datepicker, [this].concat(otherArgs)) :
+                       $.datepicker._attachDatepicker(this, options);
+       });
+};
+
+$.datepicker = new Datepicker(); // singleton instance
+$.datepicker.initialized = false;
+$.datepicker.uuid = new Date().getTime();
+$.datepicker.version = "1.7.2";
+
+// Workaround for #4055
+// Add another global to avoid noConflict issues with inline event handlers
+window.DP_jQuery = $;
+
+})(jQuery);
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/ui.datepicker.min.js b/forum/modules/template_loader.py/forum/skins/default/media/js/ui.datepicker.min.js
new file mode 100644 (file)
index 0000000..8427ef7
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * jQuery UI Datepicker 1.7.2
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Datepicker
+ *
+ * Depends:
+ *     ui.core.js
+ */
+(function($){$.extend($.ui,{datepicker:{version:"1.7.2"}});var PROP_NAME="datepicker";function Datepicker(){this.debug=false;this._curInst=null;this._keyEvent=false;this._disabledInputs=[];this._datepickerShowing=false;this._inDialog=false;this._mainDivId="ui-datepicker-div";this._inlineClass="ui-datepicker-inline";this._appendClass="ui-datepicker-append";this._triggerClass="ui-datepicker-trigger";this._dialogClass="ui-datepicker-dialog";this._disableClass="ui-datepicker-disabled";this._unselectableClass="ui-datepicker-unselectable";this._currentClass="ui-datepicker-current-day";this._dayOverClass="ui-datepicker-days-cell-over";this.regional=[];this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],dateFormat:"mm/dd/yy",firstDay:0,isRTL:false};this._defaults={showOn:"focus",showAnim:"show",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:false,hideIfNoPrevNext:false,navigationAsDateFormat:false,gotoCurrent:false,changeMonth:false,changeYear:false,showMonthAfterYear:false,yearRange:"-10:+10",showOtherMonths:false,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"normal",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:true,showButtonPanel:false};$.extend(this._defaults,this.regional[""]);this.dpDiv=$('<div id="'+this._mainDivId+'" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>')}$.extend(Datepicker.prototype,{markerClassName:"hasDatepicker",log:function(){if(this.debug){console.log.apply("",arguments)}},setDefaults:function(settings){extendRemove(this._defaults,settings||{});return this},_attachDatepicker:function(target,settings){var inlineSettings=null;for(var attrName in this._defaults){var attrValue=target.getAttribute("date:"+attrName);if(attrValue){inlineSettings=inlineSettings||{};try{inlineSettings[attrName]=eval(attrValue)}catch(err){inlineSettings[attrName]=attrValue}}}var nodeName=target.nodeName.toLowerCase();var inline=(nodeName=="div"||nodeName=="span");if(!target.id){target.id="dp"+(++this.uuid)}var inst=this._newInst($(target),inline);inst.settings=$.extend({},settings||{},inlineSettings||{});if(nodeName=="input"){this._connectDatepicker(target,inst)}else{if(inline){this._inlineDatepicker(target,inst)}}},_newInst:function(target,inline){var id=target[0].id.replace(/([:\[\]\.])/g,"\\\\$1");return{id:id,input:target,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:inline,dpDiv:(!inline?this.dpDiv:$('<div class="'+this._inlineClass+' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))}},_connectDatepicker:function(target,inst){var input=$(target);inst.append=$([]);inst.trigger=$([]);if(input.hasClass(this.markerClassName)){return}var appendText=this._get(inst,"appendText");var isRTL=this._get(inst,"isRTL");if(appendText){inst.append=$('<span class="'+this._appendClass+'">'+appendText+"</span>");input[isRTL?"before":"after"](inst.append)}var showOn=this._get(inst,"showOn");if(showOn=="focus"||showOn=="both"){input.focus(this._showDatepicker)}if(showOn=="button"||showOn=="both"){var buttonText=this._get(inst,"buttonText");var buttonImage=this._get(inst,"buttonImage");inst.trigger=$(this._get(inst,"buttonImageOnly")?$("<img/>").addClass(this._triggerClass).attr({src:buttonImage,alt:buttonText,title:buttonText}):$('<button type="button"></button>').addClass(this._triggerClass).html(buttonImage==""?buttonText:$("<img/>").attr({src:buttonImage,alt:buttonText,title:buttonText})));input[isRTL?"before":"after"](inst.trigger);inst.trigger.click(function(){if($.datepicker._datepickerShowing&&$.datepicker._lastInput==target){$.datepicker._hideDatepicker()}else{$.datepicker._showDatepicker(target)}return false})}input.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).bind("setData.datepicker",function(event,key,value){inst.settings[key]=value}).bind("getData.datepicker",function(event,key){return this._get(inst,key)});$.data(target,PROP_NAME,inst)},_inlineDatepicker:function(target,inst){var divSpan=$(target);if(divSpan.hasClass(this.markerClassName)){return}divSpan.addClass(this.markerClassName).append(inst.dpDiv).bind("setData.datepicker",function(event,key,value){inst.settings[key]=value}).bind("getData.datepicker",function(event,key){return this._get(inst,key)});$.data(target,PROP_NAME,inst);this._setDate(inst,this._getDefaultDate(inst));this._updateDatepicker(inst);this._updateAlternate(inst)},_dialogDatepicker:function(input,dateText,onSelect,settings,pos){var inst=this._dialogInst;if(!inst){var id="dp"+(++this.uuid);this._dialogInput=$('<input type="text" id="'+id+'" size="1" style="position: absolute; top: -100px;"/>');this._dialogInput.keydown(this._doKeyDown);$("body").append(this._dialogInput);inst=this._dialogInst=this._newInst(this._dialogInput,false);inst.settings={};$.data(this._dialogInput[0],PROP_NAME,inst)}extendRemove(inst.settings,settings||{});this._dialogInput.val(dateText);this._pos=(pos?(pos.length?pos:[pos.pageX,pos.pageY]):null);if(!this._pos){var browserWidth=window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth;var browserHeight=window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight;var scrollX=document.documentElement.scrollLeft||document.body.scrollLeft;var scrollY=document.documentElement.scrollTop||document.body.scrollTop;this._pos=[(browserWidth/2)-100+scrollX,(browserHeight/2)-150+scrollY]}this._dialogInput.css("left",this._pos[0]+"px").css("top",this._pos[1]+"px");inst.settings.onSelect=onSelect;this._inDialog=true;this.dpDiv.addClass(this._dialogClass);this._showDatepicker(this._dialogInput[0]);if($.blockUI){$.blockUI(this.dpDiv)}$.data(this._dialogInput[0],PROP_NAME,inst);return this},_destroyDatepicker:function(target){var $target=$(target);var inst=$.data(target,PROP_NAME);if(!$target.hasClass(this.markerClassName)){return}var nodeName=target.nodeName.toLowerCase();$.removeData(target,PROP_NAME);if(nodeName=="input"){inst.append.remove();inst.trigger.remove();$target.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress)}else{if(nodeName=="div"||nodeName=="span"){$target.removeClass(this.markerClassName).empty()}}},_enableDatepicker:function(target){var $target=$(target);var inst=$.data(target,PROP_NAME);if(!$target.hasClass(this.markerClassName)){return}var nodeName=target.nodeName.toLowerCase();if(nodeName=="input"){target.disabled=false;inst.trigger.filter("button").each(function(){this.disabled=false}).end().filter("img").css({opacity:"1.0",cursor:""})}else{if(nodeName=="div"||nodeName=="span"){var inline=$target.children("."+this._inlineClass);inline.children().removeClass("ui-state-disabled")}}this._disabledInputs=$.map(this._disabledInputs,function(value){return(value==target?null:value)})},_disableDatepicker:function(target){var $target=$(target);var inst=$.data(target,PROP_NAME);if(!$target.hasClass(this.markerClassName)){return}var nodeName=target.nodeName.toLowerCase();if(nodeName=="input"){target.disabled=true;inst.trigger.filter("button").each(function(){this.disabled=true}).end().filter("img").css({opacity:"0.5",cursor:"default"})}else{if(nodeName=="div"||nodeName=="span"){var inline=$target.children("."+this._inlineClass);inline.children().addClass("ui-state-disabled")}}this._disabledInputs=$.map(this._disabledInputs,function(value){return(value==target?null:value)});this._disabledInputs[this._disabledInputs.length]=target},_isDisabledDatepicker:function(target){if(!target){return false}for(var i=0;i<this._disabledInputs.length;i++){if(this._disabledInputs[i]==target){return true}}return false},_getInst:function(target){try{return $.data(target,PROP_NAME)}catch(err){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(target,name,value){var inst=this._getInst(target);if(arguments.length==2&&typeof name=="string"){return(name=="defaults"?$.extend({},$.datepicker._defaults):(inst?(name=="all"?$.extend({},inst.settings):this._get(inst,name)):null))}var settings=name||{};if(typeof name=="string"){settings={};settings[name]=value}if(inst){if(this._curInst==inst){this._hideDatepicker(null)}var date=this._getDateDatepicker(target);extendRemove(inst.settings,settings);this._setDateDatepicker(target,date);this._updateDatepicker(inst)}},_changeDatepicker:function(target,name,value){this._optionDatepicker(target,name,value)},_refreshDatepicker:function(target){var inst=this._getInst(target);if(inst){this._updateDatepicker(inst)}},_setDateDatepicker:function(target,date,endDate){var inst=this._getInst(target);if(inst){this._setDate(inst,date,endDate);this._updateDatepicker(inst);this._updateAlternate(inst)}},_getDateDatepicker:function(target){var inst=this._getInst(target);if(inst&&!inst.inline){this._setDateFromField(inst)}return(inst?this._getDate(inst):null)},_doKeyDown:function(event){var inst=$.datepicker._getInst(event.target);var handled=true;var isRTL=inst.dpDiv.is(".ui-datepicker-rtl");inst._keyEvent=true;if($.datepicker._datepickerShowing){switch(event.keyCode){case 9:$.datepicker._hideDatepicker(null,"");break;case 13:var sel=$("td."+$.datepicker._dayOverClass+", td."+$.datepicker._currentClass,inst.dpDiv);if(sel[0]){$.datepicker._selectDay(event.target,inst.selectedMonth,inst.selectedYear,sel[0])}else{$.datepicker._hideDatepicker(null,$.datepicker._get(inst,"duration"))}return false;break;case 27:$.datepicker._hideDatepicker(null,$.datepicker._get(inst,"duration"));break;case 33:$.datepicker._adjustDate(event.target,(event.ctrlKey?-$.datepicker._get(inst,"stepBigMonths"):-$.datepicker._get(inst,"stepMonths")),"M");break;case 34:$.datepicker._adjustDate(event.target,(event.ctrlKey?+$.datepicker._get(inst,"stepBigMonths"):+$.datepicker._get(inst,"stepMonths")),"M");break;case 35:if(event.ctrlKey||event.metaKey){$.datepicker._clearDate(event.target)}handled=event.ctrlKey||event.metaKey;break;case 36:if(event.ctrlKey||event.metaKey){$.datepicker._gotoToday(event.target)}handled=event.ctrlKey||event.metaKey;break;case 37:if(event.ctrlKey||event.metaKey){$.datepicker._adjustDate(event.target,(isRTL?+1:-1),"D")}handled=event.ctrlKey||event.metaKey;if(event.originalEvent.altKey){$.datepicker._adjustDate(event.target,(event.ctrlKey?-$.datepicker._get(inst,"stepBigMonths"):-$.datepicker._get(inst,"stepMonths")),"M")}break;case 38:if(event.ctrlKey||event.metaKey){$.datepicker._adjustDate(event.target,-7,"D")}handled=event.ctrlKey||event.metaKey;break;case 39:if(event.ctrlKey||event.metaKey){$.datepicker._adjustDate(event.target,(isRTL?-1:+1),"D")}handled=event.ctrlKey||event.metaKey;if(event.originalEvent.altKey){$.datepicker._adjustDate(event.target,(event.ctrlKey?+$.datepicker._get(inst,"stepBigMonths"):+$.datepicker._get(inst,"stepMonths")),"M")}break;case 40:if(event.ctrlKey||event.metaKey){$.datepicker._adjustDate(event.target,+7,"D")}handled=event.ctrlKey||event.metaKey;break;default:handled=false}}else{if(event.keyCode==36&&event.ctrlKey){$.datepicker._showDatepicker(this)}else{handled=false}}if(handled){event.preventDefault();event.stopPropagation()}},_doKeyPress:function(event){var inst=$.datepicker._getInst(event.target);if($.datepicker._get(inst,"constrainInput")){var chars=$.datepicker._possibleChars($.datepicker._get(inst,"dateFormat"));var chr=String.fromCharCode(event.charCode==undefined?event.keyCode:event.charCode);return event.ctrlKey||(chr<" "||!chars||chars.indexOf(chr)>-1)}},_showDatepicker:function(input){input=input.target||input;if(input.nodeName.toLowerCase()!="input"){input=$("input",input.parentNode)[0]}if($.datepicker._isDisabledDatepicker(input)||$.datepicker._lastInput==input){return}var inst=$.datepicker._getInst(input);var beforeShow=$.datepicker._get(inst,"beforeShow");extendRemove(inst.settings,(beforeShow?beforeShow.apply(input,[input,inst]):{}));$.datepicker._hideDatepicker(null,"");$.datepicker._lastInput=input;$.datepicker._setDateFromField(inst);if($.datepicker._inDialog){input.value=""}if(!$.datepicker._pos){$.datepicker._pos=$.datepicker._findPos(input);$.datepicker._pos[1]+=input.offsetHeight}var isFixed=false;$(input).parents().each(function(){isFixed|=$(this).css("position")=="fixed";return !isFixed});if(isFixed&&$.browser.opera){$.datepicker._pos[0]-=document.documentElement.scrollLeft;$.datepicker._pos[1]-=document.documentElement.scrollTop}var offset={left:$.datepicker._pos[0],top:$.datepicker._pos[1]};$.datepicker._pos=null;inst.rangeStart=null;inst.dpDiv.css({position:"absolute",display:"block",top:"-1000px"});$.datepicker._updateDatepicker(inst);offset=$.datepicker._checkOffset(inst,offset,isFixed);inst.dpDiv.css({position:($.datepicker._inDialog&&$.blockUI?"static":(isFixed?"fixed":"absolute")),display:"none",left:offset.left+"px",top:offset.top+"px"});if(!inst.inline){var showAnim=$.datepicker._get(inst,"showAnim")||"show";var duration=$.datepicker._get(inst,"duration");var postProcess=function(){$.datepicker._datepickerShowing=true;if($.browser.msie&&parseInt($.browser.version,10)<7){$("iframe.ui-datepicker-cover").css({width:inst.dpDiv.width()+4,height:inst.dpDiv.height()+4})}};if($.effects&&$.effects[showAnim]){inst.dpDiv.show(showAnim,$.datepicker._get(inst,"showOptions"),duration,postProcess)}else{inst.dpDiv[showAnim](duration,postProcess)}if(duration==""){postProcess()}if(inst.input[0].type!="hidden"){inst.input[0].focus()}$.datepicker._curInst=inst}},_updateDatepicker:function(inst){var dims={width:inst.dpDiv.width()+4,height:inst.dpDiv.height()+4};var self=this;inst.dpDiv.empty().append(this._generateHTML(inst)).find("iframe.ui-datepicker-cover").css({width:dims.width,height:dims.height}).end().find("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a").bind("mouseout",function(){$(this).removeClass("ui-state-hover");if(this.className.indexOf("ui-datepicker-prev")!=-1){$(this).removeClass("ui-datepicker-prev-hover")}if(this.className.indexOf("ui-datepicker-next")!=-1){$(this).removeClass("ui-datepicker-next-hover")}}).bind("mouseover",function(){if(!self._isDisabledDatepicker(inst.inline?inst.dpDiv.parent()[0]:inst.input[0])){$(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");$(this).addClass("ui-state-hover");if(this.className.indexOf("ui-datepicker-prev")!=-1){$(this).addClass("ui-datepicker-prev-hover")}if(this.className.indexOf("ui-datepicker-next")!=-1){$(this).addClass("ui-datepicker-next-hover")}}}).end().find("."+this._dayOverClass+" a").trigger("mouseover").end();var numMonths=this._getNumberOfMonths(inst);var cols=numMonths[1];var width=17;if(cols>1){inst.dpDiv.addClass("ui-datepicker-multi-"+cols).css("width",(width*cols)+"em")}else{inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("")}inst.dpDiv[(numMonths[0]!=1||numMonths[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi");inst.dpDiv[(this._get(inst,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl");if(inst.input&&inst.input[0].type!="hidden"&&inst==$.datepicker._curInst){$(inst.input[0]).focus()}},_checkOffset:function(inst,offset,isFixed){var dpWidth=inst.dpDiv.outerWidth();var dpHeight=inst.dpDiv.outerHeight();var inputWidth=inst.input?inst.input.outerWidth():0;var inputHeight=inst.input?inst.input.outerHeight():0;var viewWidth=(window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth)+$(document).scrollLeft();var viewHeight=(window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight)+$(document).scrollTop();offset.left-=(this._get(inst,"isRTL")?(dpWidth-inputWidth):0);offset.left-=(isFixed&&offset.left==inst.input.offset().left)?$(document).scrollLeft():0;offset.top-=(isFixed&&offset.top==(inst.input.offset().top+inputHeight))?$(document).scrollTop():0;offset.left-=(offset.left+dpWidth>viewWidth&&viewWidth>dpWidth)?Math.abs(offset.left+dpWidth-viewWidth):0;offset.top-=(offset.top+dpHeight>viewHeight&&viewHeight>dpHeight)?Math.abs(offset.top+dpHeight+inputHeight*2-viewHeight):0;return offset},_findPos:function(obj){while(obj&&(obj.type=="hidden"||obj.nodeType!=1)){obj=obj.nextSibling}var position=$(obj).offset();return[position.left,position.top]},_hideDatepicker:function(input,duration){var inst=this._curInst;if(!inst||(input&&inst!=$.data(input,PROP_NAME))){return}if(inst.stayOpen){this._selectDate("#"+inst.id,this._formatDate(inst,inst.currentDay,inst.currentMonth,inst.currentYear))}inst.stayOpen=false;if(this._datepickerShowing){duration=(duration!=null?duration:this._get(inst,"duration"));var showAnim=this._get(inst,"showAnim");var postProcess=function(){$.datepicker._tidyDialog(inst)};if(duration!=""&&$.effects&&$.effects[showAnim]){inst.dpDiv.hide(showAnim,$.datepicker._get(inst,"showOptions"),duration,postProcess)}else{inst.dpDiv[(duration==""?"hide":(showAnim=="slideDown"?"slideUp":(showAnim=="fadeIn"?"fadeOut":"hide")))](duration,postProcess)}if(duration==""){this._tidyDialog(inst)}var onClose=this._get(inst,"onClose");if(onClose){onClose.apply((inst.input?inst.input[0]:null),[(inst.input?inst.input.val():""),inst])}this._datepickerShowing=false;this._lastInput=null;if(this._inDialog){this._dialogInput.css({position:"absolute",left:"0",top:"-100px"});if($.blockUI){$.unblockUI();$("body").append(this.dpDiv)}}this._inDialog=false}this._curInst=null},_tidyDialog:function(inst){inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(event){if(!$.datepicker._curInst){return}var $target=$(event.target);if(($target.parents("#"+$.datepicker._mainDivId).length==0)&&!$target.hasClass($.datepicker.markerClassName)&&!$target.hasClass($.datepicker._triggerClass)&&$.datepicker._datepickerShowing&&!($.datepicker._inDialog&&$.blockUI)){$.datepicker._hideDatepicker(null,"")}},_adjustDate:function(id,offset,period){var target=$(id);var inst=this._getInst(target[0]);if(this._isDisabledDatepicker(target[0])){return}this._adjustInstDate(inst,offset+(period=="M"?this._get(inst,"showCurrentAtPos"):0),period);this._updateDatepicker(inst)},_gotoToday:function(id){var target=$(id);var inst=this._getInst(target[0]);if(this._get(inst,"gotoCurrent")&&inst.currentDay){inst.selectedDay=inst.currentDay;inst.drawMonth=inst.selectedMonth=inst.currentMonth;inst.drawYear=inst.selectedYear=inst.currentYear}else{var date=new Date();inst.selectedDay=date.getDate();inst.drawMonth=inst.selectedMonth=date.getMonth();inst.drawYear=inst.selectedYear=date.getFullYear()}this._notifyChange(inst);this._adjustDate(target)},_selectMonthYear:function(id,select,period){var target=$(id);var inst=this._getInst(target[0]);inst._selectingMonthYear=false;inst["selected"+(period=="M"?"Month":"Year")]=inst["draw"+(period=="M"?"Month":"Year")]=parseInt(select.options[select.selectedIndex].value,10);this._notifyChange(inst);this._adjustDate(target)},_clickMonthYear:function(id){var target=$(id);var inst=this._getInst(target[0]);if(inst.input&&inst._selectingMonthYear&&!$.browser.msie){inst.input[0].focus()}inst._selectingMonthYear=!inst._selectingMonthYear},_selectDay:function(id,month,year,td){var target=$(id);if($(td).hasClass(this._unselectableClass)||this._isDisabledDatepicker(target[0])){return}var inst=this._getInst(target[0]);inst.selectedDay=inst.currentDay=$("a",td).html();inst.selectedMonth=inst.currentMonth=month;inst.selectedYear=inst.currentYear=year;if(inst.stayOpen){inst.endDay=inst.endMonth=inst.endYear=null}this._selectDate(id,this._formatDate(inst,inst.currentDay,inst.currentMonth,inst.currentYear));if(inst.stayOpen){inst.rangeStart=this._daylightSavingAdjust(new Date(inst.currentYear,inst.currentMonth,inst.currentDay));this._updateDatepicker(inst)}},_clearDate:function(id){var target=$(id);var inst=this._getInst(target[0]);inst.stayOpen=false;inst.endDay=inst.endMonth=inst.endYear=inst.rangeStart=null;this._selectDate(target,"")},_selectDate:function(id,dateStr){var target=$(id);var inst=this._getInst(target[0]);dateStr=(dateStr!=null?dateStr:this._formatDate(inst));if(inst.input){inst.input.val(dateStr)}this._updateAlternate(inst);var onSelect=this._get(inst,"onSelect");if(onSelect){onSelect.apply((inst.input?inst.input[0]:null),[dateStr,inst])}else{if(inst.input){inst.input.trigger("change")}}if(inst.inline){this._updateDatepicker(inst)}else{if(!inst.stayOpen){this._hideDatepicker(null,this._get(inst,"duration"));this._lastInput=inst.input[0];if(typeof(inst.input[0])!="object"){inst.input[0].focus()}this._lastInput=null}}},_updateAlternate:function(inst){var altField=this._get(inst,"altField");if(altField){var altFormat=this._get(inst,"altFormat")||this._get(inst,"dateFormat");var date=this._getDate(inst);dateStr=this.formatDate(altFormat,date,this._getFormatConfig(inst));$(altField).each(function(){$(this).val(dateStr)})}},noWeekends:function(date){var day=date.getDay();return[(day>0&&day<6),""]},iso8601Week:function(date){var checkDate=new Date(date.getFullYear(),date.getMonth(),date.getDate());var firstMon=new Date(checkDate.getFullYear(),1-1,4);var firstDay=firstMon.getDay()||7;firstMon.setDate(firstMon.getDate()+1-firstDay);if(firstDay<4&&checkDate<firstMon){checkDate.setDate(checkDate.getDate()-3);return $.datepicker.iso8601Week(checkDate)}else{if(checkDate>new Date(checkDate.getFullYear(),12-1,28)){firstDay=new Date(checkDate.getFullYear()+1,1-1,4).getDay()||7;if(firstDay>4&&(checkDate.getDay()||7)<firstDay-3){return 1}}}return Math.floor(((checkDate-firstMon)/86400000)/7)+1},parseDate:function(format,value,settings){if(format==null||value==null){throw"Invalid arguments"}value=(typeof value=="object"?value.toString():value+"");if(value==""){return null}var shortYearCutoff=(settings?settings.shortYearCutoff:null)||this._defaults.shortYearCutoff;var dayNamesShort=(settings?settings.dayNamesShort:null)||this._defaults.dayNamesShort;var dayNames=(settings?settings.dayNames:null)||this._defaults.dayNames;var monthNamesShort=(settings?settings.monthNamesShort:null)||this._defaults.monthNamesShort;var monthNames=(settings?settings.monthNames:null)||this._defaults.monthNames;var year=-1;var month=-1;var day=-1;var doy=-1;var literal=false;var lookAhead=function(match){var matches=(iFormat+1<format.length&&format.charAt(iFormat+1)==match);if(matches){iFormat++}return matches};var getNumber=function(match){lookAhead(match);var origSize=(match=="@"?14:(match=="y"?4:(match=="o"?3:2)));var size=origSize;var num=0;while(size>0&&iValue<value.length&&value.charAt(iValue)>="0"&&value.charAt(iValue)<="9"){num=num*10+parseInt(value.charAt(iValue++),10);size--}if(size==origSize){throw"Missing number at position "+iValue}return num};var getName=function(match,shortNames,longNames){var names=(lookAhead(match)?longNames:shortNames);var size=0;for(var j=0;j<names.length;j++){size=Math.max(size,names[j].length)}var name="";var iInit=iValue;while(size>0&&iValue<value.length){name+=value.charAt(iValue++);for(var i=0;i<names.length;i++){if(name==names[i]){return i+1}}size--}throw"Unknown name at position "+iInit};var checkLiteral=function(){if(value.charAt(iValue)!=format.charAt(iFormat)){throw"Unexpected literal at position "+iValue}iValue++};var iValue=0;for(var iFormat=0;iFormat<format.length;iFormat++){if(literal){if(format.charAt(iFormat)=="'"&&!lookAhead("'")){literal=false}else{checkLiteral()}}else{switch(format.charAt(iFormat)){case"d":day=getNumber("d");break;case"D":getName("D",dayNamesShort,dayNames);break;case"o":doy=getNumber("o");break;case"m":month=getNumber("m");break;case"M":month=getName("M",monthNamesShort,monthNames);break;case"y":year=getNumber("y");break;case"@":var date=new Date(getNumber("@"));year=date.getFullYear();month=date.getMonth()+1;day=date.getDate();break;case"'":if(lookAhead("'")){checkLiteral()}else{literal=true}break;default:checkLiteral()}}}if(year==-1){year=new Date().getFullYear()}else{if(year<100){year+=new Date().getFullYear()-new Date().getFullYear()%100+(year<=shortYearCutoff?0:-100)}}if(doy>-1){month=1;day=doy;do{var dim=this._getDaysInMonth(year,month-1);if(day<=dim){break}month++;day-=dim}while(true)}var date=this._daylightSavingAdjust(new Date(year,month-1,day));if(date.getFullYear()!=year||date.getMonth()+1!=month||date.getDate()!=day){throw"Invalid date"}return date},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TIMESTAMP:"@",W3C:"yy-mm-dd",formatDate:function(format,date,settings){if(!date){return""}var dayNamesShort=(settings?settings.dayNamesShort:null)||this._defaults.dayNamesShort;var dayNames=(settings?settings.dayNames:null)||this._defaults.dayNames;var monthNamesShort=(settings?settings.monthNamesShort:null)||this._defaults.monthNamesShort;var monthNames=(settings?settings.monthNames:null)||this._defaults.monthNames;var lookAhead=function(match){var matches=(iFormat+1<format.length&&format.charAt(iFormat+1)==match);if(matches){iFormat++}return matches};var formatNumber=function(match,value,len){var num=""+value;if(lookAhead(match)){while(num.length<len){num="0"+num}}return num};var formatName=function(match,value,shortNames,longNames){return(lookAhead(match)?longNames[value]:shortNames[value])};var output="";var literal=false;if(date){for(var iFormat=0;iFormat<format.length;iFormat++){if(literal){if(format.charAt(iFormat)=="'"&&!lookAhead("'")){literal=false}else{output+=format.charAt(iFormat)}}else{switch(format.charAt(iFormat)){case"d":output+=formatNumber("d",date.getDate(),2);break;case"D":output+=formatName("D",date.getDay(),dayNamesShort,dayNames);break;case"o":var doy=date.getDate();for(var m=date.getMonth()-1;m>=0;m--){doy+=this._getDaysInMonth(date.getFullYear(),m)}output+=formatNumber("o",doy,3);break;case"m":output+=formatNumber("m",date.getMonth()+1,2);break;case"M":output+=formatName("M",date.getMonth(),monthNamesShort,monthNames);break;case"y":output+=(lookAhead("y")?date.getFullYear():(date.getYear()%100<10?"0":"")+date.getYear()%100);break;case"@":output+=date.getTime();break;case"'":if(lookAhead("'")){output+="'"}else{literal=true}break;default:output+=format.charAt(iFormat)}}}}return output},_possibleChars:function(format){var chars="";var literal=false;for(var iFormat=0;iFormat<format.length;iFormat++){if(literal){if(format.charAt(iFormat)=="'"&&!lookAhead("'")){literal=false}else{chars+=format.charAt(iFormat)}}else{switch(format.charAt(iFormat)){case"d":case"m":case"y":case"@":chars+="0123456789";break;case"D":case"M":return null;case"'":if(lookAhead("'")){chars+="'"}else{literal=true}break;default:chars+=format.charAt(iFormat)}}}return chars},_get:function(inst,name){return inst.settings[name]!==undefined?inst.settings[name]:this._defaults[name]},_setDateFromField:function(inst){var dateFormat=this._get(inst,"dateFormat");var dates=inst.input?inst.input.val():null;inst.endDay=inst.endMonth=inst.endYear=null;var date=defaultDate=this._getDefaultDate(inst);var settings=this._getFormatConfig(inst);try{date=this.parseDate(dateFormat,dates,settings)||defaultDate}catch(event){this.log(event);date=defaultDate}inst.selectedDay=date.getDate();inst.drawMonth=inst.selectedMonth=date.getMonth();inst.drawYear=inst.selectedYear=date.getFullYear();inst.currentDay=(dates?date.getDate():0);inst.currentMonth=(dates?date.getMonth():0);inst.currentYear=(dates?date.getFullYear():0);this._adjustInstDate(inst)},_getDefaultDate:function(inst){var date=this._determineDate(this._get(inst,"defaultDate"),new Date());var minDate=this._getMinMaxDate(inst,"min",true);var maxDate=this._getMinMaxDate(inst,"max");date=(minDate&&date<minDate?minDate:date);date=(maxDate&&date>maxDate?maxDate:date);return date},_determineDate:function(date,defaultDate){var offsetNumeric=function(offset){var date=new Date();date.setDate(date.getDate()+offset);return date};var offsetString=function(offset,getDaysInMonth){var date=new Date();var year=date.getFullYear();var month=date.getMonth();var day=date.getDate();var pattern=/([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;var matches=pattern.exec(offset);while(matches){switch(matches[2]||"d"){case"d":case"D":day+=parseInt(matches[1],10);break;case"w":case"W":day+=parseInt(matches[1],10)*7;break;case"m":case"M":month+=parseInt(matches[1],10);day=Math.min(day,getDaysInMonth(year,month));break;case"y":case"Y":year+=parseInt(matches[1],10);day=Math.min(day,getDaysInMonth(year,month));break}matches=pattern.exec(offset)}return new Date(year,month,day)};date=(date==null?defaultDate:(typeof date=="string"?offsetString(date,this._getDaysInMonth):(typeof date=="number"?(isNaN(date)?defaultDate:offsetNumeric(date)):date)));date=(date&&date.toString()=="Invalid Date"?defaultDate:date);if(date){date.setHours(0);date.setMinutes(0);date.setSeconds(0);date.setMilliseconds(0)}return this._daylightSavingAdjust(date)},_daylightSavingAdjust:function(date){if(!date){return null}date.setHours(date.getHours()>12?date.getHours()+2:0);return date},_setDate:function(inst,date,endDate){var clear=!(date);var origMonth=inst.selectedMonth;var origYear=inst.selectedYear;date=this._determineDate(date,new Date());inst.selectedDay=inst.currentDay=date.getDate();inst.drawMonth=inst.selectedMonth=inst.currentMonth=date.getMonth();inst.drawYear=inst.selectedYear=inst.currentYear=date.getFullYear();if(origMonth!=inst.selectedMonth||origYear!=inst.selectedYear){this._notifyChange(inst)}this._adjustInstDate(inst);if(inst.input){inst.input.val(clear?"":this._formatDate(inst))}},_getDate:function(inst){var startDate=(!inst.currentYear||(inst.input&&inst.input.val()=="")?null:this._daylightSavingAdjust(new Date(inst.currentYear,inst.currentMonth,inst.currentDay)));return startDate},_generateHTML:function(inst){var today=new Date();today=this._daylightSavingAdjust(new Date(today.getFullYear(),today.getMonth(),today.getDate()));var isRTL=this._get(inst,"isRTL");var showButtonPanel=this._get(inst,"showButtonPanel");var hideIfNoPrevNext=this._get(inst,"hideIfNoPrevNext");var navigationAsDateFormat=this._get(inst,"navigationAsDateFormat");var numMonths=this._getNumberOfMonths(inst);var showCurrentAtPos=this._get(inst,"showCurrentAtPos");var stepMonths=this._get(inst,"stepMonths");var stepBigMonths=this._get(inst,"stepBigMonths");var isMultiMonth=(numMonths[0]!=1||numMonths[1]!=1);var currentDate=this._daylightSavingAdjust((!inst.currentDay?new Date(9999,9,9):new Date(inst.currentYear,inst.currentMonth,inst.currentDay)));var minDate=this._getMinMaxDate(inst,"min",true);var maxDate=this._getMinMaxDate(inst,"max");var drawMonth=inst.drawMonth-showCurrentAtPos;var drawYear=inst.drawYear;if(drawMonth<0){drawMonth+=12;drawYear--}if(maxDate){var maxDraw=this._daylightSavingAdjust(new Date(maxDate.getFullYear(),maxDate.getMonth()-numMonths[1]+1,maxDate.getDate()));maxDraw=(minDate&&maxDraw<minDate?minDate:maxDraw);while(this._daylightSavingAdjust(new Date(drawYear,drawMonth,1))>maxDraw){drawMonth--;if(drawMonth<0){drawMonth=11;drawYear--}}}inst.drawMonth=drawMonth;inst.drawYear=drawYear;var prevText=this._get(inst,"prevText");prevText=(!navigationAsDateFormat?prevText:this.formatDate(prevText,this._daylightSavingAdjust(new Date(drawYear,drawMonth-stepMonths,1)),this._getFormatConfig(inst)));var prev=(this._canAdjustMonth(inst,-1,drawYear,drawMonth)?'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#'+inst.id+"', -"+stepMonths+", 'M');\" title=\""+prevText+'"><span class="ui-icon ui-icon-circle-triangle-'+(isRTL?"e":"w")+'">'+prevText+"</span></a>":(hideIfNoPrevNext?"":'<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+prevText+'"><span class="ui-icon ui-icon-circle-triangle-'+(isRTL?"e":"w")+'">'+prevText+"</span></a>"));var nextText=this._get(inst,"nextText");nextText=(!navigationAsDateFormat?nextText:this.formatDate(nextText,this._daylightSavingAdjust(new Date(drawYear,drawMonth+stepMonths,1)),this._getFormatConfig(inst)));var next=(this._canAdjustMonth(inst,+1,drawYear,drawMonth)?'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#'+inst.id+"', +"+stepMonths+", 'M');\" title=\""+nextText+'"><span class="ui-icon ui-icon-circle-triangle-'+(isRTL?"w":"e")+'">'+nextText+"</span></a>":(hideIfNoPrevNext?"":'<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+nextText+'"><span class="ui-icon ui-icon-circle-triangle-'+(isRTL?"w":"e")+'">'+nextText+"</span></a>"));var currentText=this._get(inst,"currentText");var gotoDate=(this._get(inst,"gotoCurrent")&&inst.currentDay?currentDate:today);currentText=(!navigationAsDateFormat?currentText:this.formatDate(currentText,gotoDate,this._getFormatConfig(inst)));var controls=(!inst.inline?'<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery.datepicker._hideDatepicker();">'+this._get(inst,"closeText")+"</button>":"");var buttonPanel=(showButtonPanel)?'<div class="ui-datepicker-buttonpane ui-widget-content">'+(isRTL?controls:"")+(this._isInRange(inst,gotoDate)?'<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery.datepicker._gotoToday(\'#'+inst.id+"');\">"+currentText+"</button>":"")+(isRTL?"":controls)+"</div>":"";var firstDay=parseInt(this._get(inst,"firstDay"),10);firstDay=(isNaN(firstDay)?0:firstDay);var dayNames=this._get(inst,"dayNames");var dayNamesShort=this._get(inst,"dayNamesShort");var dayNamesMin=this._get(inst,"dayNamesMin");var monthNames=this._get(inst,"monthNames");var monthNamesShort=this._get(inst,"monthNamesShort");var beforeShowDay=this._get(inst,"beforeShowDay");var showOtherMonths=this._get(inst,"showOtherMonths");var calculateWeek=this._get(inst,"calculateWeek")||this.iso8601Week;var endDate=inst.endDay?this._daylightSavingAdjust(new Date(inst.endYear,inst.endMonth,inst.endDay)):currentDate;var defaultDate=this._getDefaultDate(inst);var html="";for(var row=0;row<numMonths[0];row++){var group="";for(var col=0;col<numMonths[1];col++){var selectedDate=this._daylightSavingAdjust(new Date(drawYear,drawMonth,inst.selectedDay));var cornerClass=" ui-corner-all";var calender="";if(isMultiMonth){calender+='<div class="ui-datepicker-group ui-datepicker-group-';switch(col){case 0:calender+="first";cornerClass=" ui-corner-"+(isRTL?"right":"left");break;case numMonths[1]-1:calender+="last";cornerClass=" ui-corner-"+(isRTL?"left":"right");break;default:calender+="middle";cornerClass="";break}calender+='">'}calender+='<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix'+cornerClass+'">'+(/all|left/.test(cornerClass)&&row==0?(isRTL?next:prev):"")+(/all|right/.test(cornerClass)&&row==0?(isRTL?prev:next):"")+this._generateMonthYearHeader(inst,drawMonth,drawYear,minDate,maxDate,selectedDate,row>0||col>0,monthNames,monthNamesShort)+'</div><table class="ui-datepicker-calendar"><thead><tr>';var thead="";for(var dow=0;dow<7;dow++){var day=(dow+firstDay)%7;thead+="<th"+((dow+firstDay+6)%7>=5?' class="ui-datepicker-week-end"':"")+'><span title="'+dayNames[day]+'">'+dayNamesMin[day]+"</span></th>"}calender+=thead+"</tr></thead><tbody>";var daysInMonth=this._getDaysInMonth(drawYear,drawMonth);if(drawYear==inst.selectedYear&&drawMonth==inst.selectedMonth){inst.selectedDay=Math.min(inst.selectedDay,daysInMonth)}var leadDays=(this._getFirstDayOfMonth(drawYear,drawMonth)-firstDay+7)%7;var numRows=(isMultiMonth?6:Math.ceil((leadDays+daysInMonth)/7));var printDate=this._daylightSavingAdjust(new Date(drawYear,drawMonth,1-leadDays));for(var dRow=0;dRow<numRows;dRow++){calender+="<tr>";var tbody="";for(var dow=0;dow<7;dow++){var daySettings=(beforeShowDay?beforeShowDay.apply((inst.input?inst.input[0]:null),[printDate]):[true,""]);var otherMonth=(printDate.getMonth()!=drawMonth);var unselectable=otherMonth||!daySettings[0]||(minDate&&printDate<minDate)||(maxDate&&printDate>maxDate);tbody+='<td class="'+((dow+firstDay+6)%7>=5?" ui-datepicker-week-end":"")+(otherMonth?" ui-datepicker-other-month":"")+((printDate.getTime()==selectedDate.getTime()&&drawMonth==inst.selectedMonth&&inst._keyEvent)||(defaultDate.getTime()==printDate.getTime()&&defaultDate.getTime()==selectedDate.getTime())?" "+this._dayOverClass:"")+(unselectable?" "+this._unselectableClass+" ui-state-disabled":"")+(otherMonth&&!showOtherMonths?"":" "+daySettings[1]+(printDate.getTime()>=currentDate.getTime()&&printDate.getTime()<=endDate.getTime()?" "+this._currentClass:"")+(printDate.getTime()==today.getTime()?" ui-datepicker-today":""))+'"'+((!otherMonth||showOtherMonths)&&daySettings[2]?' title="'+daySettings[2]+'"':"")+(unselectable?"":" onclick=\"DP_jQuery.datepicker._selectDay('#"+inst.id+"',"+drawMonth+","+drawYear+', this);return false;"')+">"+(otherMonth?(showOtherMonths?printDate.getDate():"&#xa0;"):(unselectable?'<span class="ui-state-default">'+printDate.getDate()+"</span>":'<a class="ui-state-default'+(printDate.getTime()==today.getTime()?" ui-state-highlight":"")+(printDate.getTime()>=currentDate.getTime()&&printDate.getTime()<=endDate.getTime()?" ui-state-active":"")+'" href="#">'+printDate.getDate()+"</a>"))+"</td>";printDate.setDate(printDate.getDate()+1);printDate=this._daylightSavingAdjust(printDate)}calender+=tbody+"</tr>"}drawMonth++;if(drawMonth>11){drawMonth=0;drawYear++}calender+="</tbody></table>"+(isMultiMonth?"</div>"+((numMonths[0]>0&&col==numMonths[1]-1)?'<div class="ui-datepicker-row-break"></div>':""):"");group+=calender}html+=group}html+=buttonPanel+($.browser.msie&&parseInt($.browser.version,10)<7&&!inst.inline?'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>':"");inst._keyEvent=false;return html},_generateMonthYearHeader:function(inst,drawMonth,drawYear,minDate,maxDate,selectedDate,secondary,monthNames,monthNamesShort){minDate=(inst.rangeStart&&minDate&&selectedDate<minDate?selectedDate:minDate);var changeMonth=this._get(inst,"changeMonth");var changeYear=this._get(inst,"changeYear");var showMonthAfterYear=this._get(inst,"showMonthAfterYear");var html='<div class="ui-datepicker-title">';var monthHtml="";if(secondary||!changeMonth){monthHtml+='<span class="ui-datepicker-month">'+monthNames[drawMonth]+"</span> "}else{var inMinYear=(minDate&&minDate.getFullYear()==drawYear);var inMaxYear=(maxDate&&maxDate.getFullYear()==drawYear);monthHtml+='<select class="ui-datepicker-month" onchange="DP_jQuery.datepicker._selectMonthYear(\'#'+inst.id+"', this, 'M');\" onclick=\"DP_jQuery.datepicker._clickMonthYear('#"+inst.id+"');\">";for(var month=0;month<12;month++){if((!inMinYear||month>=minDate.getMonth())&&(!inMaxYear||month<=maxDate.getMonth())){monthHtml+='<option value="'+month+'"'+(month==drawMonth?' selected="selected"':"")+">"+monthNamesShort[month]+"</option>"}}monthHtml+="</select>"}if(!showMonthAfterYear){html+=monthHtml+((secondary||changeMonth||changeYear)&&(!(changeMonth&&changeYear))?"&#xa0;":"")}if(secondary||!changeYear){html+='<span class="ui-datepicker-year">'+drawYear+"</span>"}else{var years=this._get(inst,"yearRange").split(":");var year=0;var endYear=0;if(years.length!=2){year=drawYear-10;endYear=drawYear+10}else{if(years[0].charAt(0)=="+"||years[0].charAt(0)=="-"){year=drawYear+parseInt(years[0],10);endYear=drawYear+parseInt(years[1],10)}else{year=parseInt(years[0],10);endYear=parseInt(years[1],10)}}year=(minDate?Math.max(year,minDate.getFullYear()):year);endYear=(maxDate?Math.min(endYear,maxDate.getFullYear()):endYear);html+='<select class="ui-datepicker-year" onchange="DP_jQuery.datepicker._selectMonthYear(\'#'+inst.id+"', this, 'Y');\" onclick=\"DP_jQuery.datepicker._clickMonthYear('#"+inst.id+"');\">";for(;year<=endYear;year++){html+='<option value="'+year+'"'+(year==drawYear?' selected="selected"':"")+">"+year+"</option>"}html+="</select>"}if(showMonthAfterYear){html+=(secondary||changeMonth||changeYear?"&#xa0;":"")+monthHtml}html+="</div>";return html},_adjustInstDate:function(inst,offset,period){var year=inst.drawYear+(period=="Y"?offset:0);var month=inst.drawMonth+(period=="M"?offset:0);var day=Math.min(inst.selectedDay,this._getDaysInMonth(year,month))+(period=="D"?offset:0);var date=this._daylightSavingAdjust(new Date(year,month,day));var minDate=this._getMinMaxDate(inst,"min",true);var maxDate=this._getMinMaxDate(inst,"max");date=(minDate&&date<minDate?minDate:date);date=(maxDate&&date>maxDate?maxDate:date);inst.selectedDay=date.getDate();inst.drawMonth=inst.selectedMonth=date.getMonth();inst.drawYear=inst.selectedYear=date.getFullYear();if(period=="M"||period=="Y"){this._notifyChange(inst)}},_notifyChange:function(inst){var onChange=this._get(inst,"onChangeMonthYear");if(onChange){onChange.apply((inst.input?inst.input[0]:null),[inst.selectedYear,inst.selectedMonth+1,inst])}},_getNumberOfMonths:function(inst){var numMonths=this._get(inst,"numberOfMonths");return(numMonths==null?[1,1]:(typeof numMonths=="number"?[1,numMonths]:numMonths))},_getMinMaxDate:function(inst,minMax,checkRange){var date=this._determineDate(this._get(inst,minMax+"Date"),null);return(!checkRange||!inst.rangeStart?date:(!date||inst.rangeStart>date?inst.rangeStart:date))},_getDaysInMonth:function(year,month){return 32-new Date(year,month,32).getDate()},_getFirstDayOfMonth:function(year,month){return new Date(year,month,1).getDay()},_canAdjustMonth:function(inst,offset,curYear,curMonth){var numMonths=this._getNumberOfMonths(inst);var date=this._daylightSavingAdjust(new Date(curYear,curMonth+(offset<0?offset:numMonths[1]),1));if(offset<0){date.setDate(this._getDaysInMonth(date.getFullYear(),date.getMonth()))}return this._isInRange(inst,date)},_isInRange:function(inst,date){var newMinDate=(!inst.rangeStart?null:this._daylightSavingAdjust(new Date(inst.selectedYear,inst.selectedMonth,inst.selectedDay)));newMinDate=(newMinDate&&inst.rangeStart<newMinDate?inst.rangeStart:newMinDate);var minDate=newMinDate||this._getMinMaxDate(inst,"min");var maxDate=this._getMinMaxDate(inst,"max");return((!minDate||date>=minDate)&&(!maxDate||date<=maxDate))},_getFormatConfig:function(inst){var shortYearCutoff=this._get(inst,"shortYearCutoff");shortYearCutoff=(typeof shortYearCutoff!="string"?shortYearCutoff:new Date().getFullYear()%100+parseInt(shortYearCutoff,10));return{shortYearCutoff:shortYearCutoff,dayNamesShort:this._get(inst,"dayNamesShort"),dayNames:this._get(inst,"dayNames"),monthNamesShort:this._get(inst,"monthNamesShort"),monthNames:this._get(inst,"monthNames")}},_formatDate:function(inst,day,month,year){if(!day){inst.currentDay=inst.selectedDay;inst.currentMonth=inst.selectedMonth;inst.currentYear=inst.selectedYear}var date=(day?(typeof day=="object"?day:this._daylightSavingAdjust(new Date(year,month,day))):this._daylightSavingAdjust(new Date(inst.currentYear,inst.currentMonth,inst.currentDay)));return this.formatDate(this._get(inst,"dateFormat"),date,this._getFormatConfig(inst))}});function extendRemove(target,props){$.extend(target,props);for(var name in props){if(props[name]==null||props[name]==undefined){target[name]=props[name]}}return target}function isArray(a){return(a&&(($.browser.safari&&typeof a=="object"&&a.length)||(a.constructor&&a.constructor.toString().match(/\Array\(\)/))))}$.fn.datepicker=function(options){if(!$.datepicker.initialized){$(document).mousedown($.datepicker._checkExternalClick).find("body").append($.datepicker.dpDiv);$.datepicker.initialized=true}var otherArgs=Array.prototype.slice.call(arguments,1);if(typeof options=="string"&&(options=="isDisabled"||options=="getDate")){return $.datepicker["_"+options+"Datepicker"].apply($.datepicker,[this[0]].concat(otherArgs))}if(options=="option"&&arguments.length==2&&typeof arguments[1]=="string"){return $.datepicker["_"+options+"Datepicker"].apply($.datepicker,[this[0]].concat(otherArgs))}return this.each(function(){typeof options=="string"?$.datepicker["_"+options+"Datepicker"].apply($.datepicker,[this].concat(otherArgs)):$.datepicker._attachDatepicker(this,options)})};$.datepicker=new Datepicker();$.datepicker.initialized=false;$.datepicker.uuid=new Date().getTime();$.datepicker.version="1.7.2";window.DP_jQuery=$})(jQuery);
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/bg-fill.png b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/bg-fill.png
new file mode 100644 (file)
index 0000000..ec503ce
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/bg-fill.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/bg.png b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/bg.png
new file mode 100644 (file)
index 0000000..bcaed31
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/bg.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/blockquote.png b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/blockquote.png
new file mode 100644 (file)
index 0000000..537864a
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/blockquote.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/bold.png b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/bold.png
new file mode 100644 (file)
index 0000000..eac2763
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/bold.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/code.png b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/code.png
new file mode 100644 (file)
index 0000000..dc1011c
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/code.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/h1.png b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/h1.png
new file mode 100644 (file)
index 0000000..96baecb
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/h1.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/hr.png b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/hr.png
new file mode 100644 (file)
index 0000000..08be8e5
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/hr.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/img.png b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/img.png
new file mode 100644 (file)
index 0000000..596b989
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/img.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/italic.png b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/italic.png
new file mode 100644 (file)
index 0000000..412b0fc
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/italic.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/link.png b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/link.png
new file mode 100644 (file)
index 0000000..1e11500
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/link.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/ol.png b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/ol.png
new file mode 100644 (file)
index 0000000..3df2b9b
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/ol.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/redo.png b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/redo.png
new file mode 100644 (file)
index 0000000..736a78b
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/redo.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/separator.png b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/separator.png
new file mode 100644 (file)
index 0000000..9cb87b9
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/separator.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/ul.png b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/ul.png
new file mode 100644 (file)
index 0000000..978be7e
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/ul.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/undo.png b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/undo.png
new file mode 100644 (file)
index 0000000..533faaf
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/undo.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/wmd-buttons.png b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/wmd-buttons.png
new file mode 100644 (file)
index 0000000..50b3709
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/wmd-buttons.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/wmd-buttons.psd b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/wmd-buttons.psd
new file mode 100644 (file)
index 0000000..e61ff37
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/wmd-buttons.psd differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/wmd-on.png b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/wmd-on.png
new file mode 100644 (file)
index 0000000..4844ae9
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/wmd-on.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/wmd.png b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/wmd.png
new file mode 100644 (file)
index 0000000..04177fb
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/images/wmd.png differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/showdown-min.js b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/showdown-min.js
new file mode 100644 (file)
index 0000000..073613b
--- /dev/null
@@ -0,0 +1 @@
+var Attacklab=Attacklab||{};Attacklab.showdown=Attacklab.showdown||{};Attacklab.showdown.converter=function(){var a;var j;var A;var i=0;this.makeHtml=function(H){a=new Array();j=new Array();A=new Array();H=H.replace(/~/g,"~T");H=H.replace(/\$/g,"~D");H=H.replace(/\r\n/g,"\n");H=H.replace(/\r/g,"\n");H="\n\n"+H+"\n\n";H=z(H);H=H.replace(/^[ \t]+$/mg,"");H=m(H);H=d(H);H=G(H);H=q(H);H=H.replace(/~D/g,"$$");H=H.replace(/~T/g,"~");return H};var d=function(H){var H=H.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|\Z)/gm,function(K,M,L,J,I){M=M.toLowerCase();a[M]=h(L);if(J){return J+I}else{if(I){j[M]=I.replace(/"/g,"&quot;")}}return""});return H};var m=function(J){J=J.replace(/\n/g,"\n\n");var I="p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del";var H="p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math";J=J.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm,x);J=J.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math)\b[^\r]*?.*<\/\2>[ \t]*(?=\n+)\n)/gm,x);J=J.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,x);J=J.replace(/(\n\n[ ]{0,3}<!(--[^\r]*?--\s*)+>[ \t]*(?=\n{2,}))/g,x);J=J.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,x);J=J.replace(/\n\n/g,"\n");return J};var x=function(H,I){var J=I;J=J.replace(/\n\n/g,"\n");J=J.replace(/^\n/,"");J=J.replace(/\n+$/g,"");J="\n\n~K"+(A.push(J)-1)+"K\n\n";return J};var G=function(I){I=f(I);var H=o("<hr />");I=I.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm,H);I=I.replace(/^[ ]{0,2}([ ]?-[ ]?){3,}[ \t]*$/gm,H);I=I.replace(/^[ ]{0,2}([ ]?_[ ]?){3,}[ \t]*$/gm,H);I=E(I);I=b(I);I=u(I);I=m(I);I=g(I);return I};var r=function(H){H=C(H);H=l(H);H=e(H);H=F(H);H=y(H);H=n(H);H=h(H);H=c(H);H=H.replace(/  +\n/g," <br />\n");return H};var l=function(I){var H=/(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--.*?--\s*)+>)/gi;I=I.replace(H,function(K){var J=K.replace(/(.)<\/?code>(?=.)/g,"$1`");J=w(J,"\\`*_");return J});return I};var y=function(H){H=H.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,D);H=H.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()<?(.*?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,D);H=H.replace(/(\[([^\[\]]+)\])()()()()()/g,D);return H};var D=function(N,T,S,R,Q,P,M,L){if(L==undefined){L=""}var K=T;var I=S;var J=R.toLowerCase();var H=Q;var O=L;if(H==""){if(J==""){J=I.toLowerCase().replace(/ ?\n/g," ")}H="#"+J;if(a[J]!=undefined){H=a[J];if(j[J]!=undefined){O=j[J]}}else{if(K.search(/\(\s*\)$/m)>-1){H=""}else{return K}}}H=w(H,"*_");var U='<a href="'+H+'"';if(O!=""){O=O.replace(/"/g,"&quot;");O=w(O,"*_");U+=' title="'+O+'"'}U+=">"+I+"</a>";return U};var F=function(H){H=H.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,t);H=H.replace(/(!\[(.*?)\]\s?\([ \t]*()<?(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,t);return H};var t=function(N,T,S,R,Q,P,M,L){var K=T;var J=S;var I=R.toLowerCase();var H=Q;var O=L;if(!O){O=""}if(H==""){if(I==""){I=J.toLowerCase().replace(/ ?\n/g," ")}H="#"+I;if(a[I]!=undefined){H=a[I];if(j[I]!=undefined){O=j[I]}}else{return K}}J=J.replace(/"/g,"&quot;");H=w(H,"*_");var U='<img src="'+H+'" alt="'+J+'"';O=O.replace(/"/g,"&quot;");O=w(O,"*_");U+=' title="'+O+'"';U+=" />";return U};var f=function(H){H=H.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm,function(I,J){return o("<h1>"+r(J)+"</h1>")});H=H.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm,function(J,I){return o("<h2>"+r(I)+"</h2>")});H=H.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm,function(I,L,K){var J=L.length;return o("<h"+J+">"+r(K)+"</h"+J+">")});return H};var p;var E=function(I){I+="~0";var H=/^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm;if(i){I=I.replace(H,function(K,N,M){var O=N;var L=(M.search(/[*+-]/g)>-1)?"ul":"ol";O=O.replace(/\n{2,}/g,"\n\n\n");var J=p(O);J=J.replace(/\s+$/,"");J="<"+L+">"+J+"</"+L+">\n";return J})}else{H=/(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g;I=I.replace(H,function(L,P,N,K){var O=P;var Q=N;var M=(K.search(/[*+-]/g)>-1)?"ul":"ol";var Q=Q.replace(/\n{2,}/g,"\n\n\n");var J=p(Q);J=O+"<"+M+">\n"+J+"</"+M+">\n";return J})}I=I.replace(/~0/,"");return I};p=function(H){i++;H=H.replace(/\n{2,}$/,"\n");H+="~0";H=H.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm,function(K,M,L,J,I){var O=I;var N=M;var P=L;if(N||(O.search(/\n{2,}/)>-1)){O=G(s(O))}else{O=E(s(O));O=O.replace(/\n$/,"");O=r(O)}return"<li>"+O+"</li>\n"});H=H.replace(/~0/g,"");i--;return H};var b=function(H){H+="~0";H=H.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g,function(I,K,J){var L=K;var M=J;L=v(s(L));L=z(L);L=L.replace(/^\n+/g,"");L=L.replace(/\n+$/g,"");L="<pre><code>"+L+"\n</code></pre>";return o(L)+M});H=H.replace(/~0/,"");return H};var o=function(H){H=H.replace(/(^\n+|\n+$)/g,"");return"\n\n~K"+(A.push(H)-1)+"K\n\n"};var C=function(H){H=H.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,function(K,M,L,J,I){var N=J;N=N.replace(/^([ \t]*)/g,"");N=N.replace(/[ \t]*$/g,"");N=v(N);return M+"<code>"+N+"</code>"});return H};var v=function(H){H=H.replace(/&/g,"&amp;");H=H.replace(/</g,"&lt;");H=H.replace(/>/g,"&gt;");H=w(H,"*_{}[]\\",false);return H};var c=function(H){H=H.replace(/(\*\*|__)(?=\S)([^\r]*?\S[\*_]*)\1/g,"<strong>$2</strong>");H=H.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g,"<em>$2</em>");return H};var u=function(H){H=H.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm,function(I,J){var K=J;K=K.replace(/^[ \t]*>[ \t]?/gm,"~0");K=K.replace(/~0/g,"");K=K.replace(/^[ \t]+$/gm,"");K=G(K);K=K.replace(/(^|\n)/g,"$1  ");K=K.replace(/(\s*<pre>[^\r]+?<\/pre>)/gm,function(L,M){var N=M;N=N.replace(/^  /mg,"~0");N=N.replace(/~0/g,"");return N});return o("<blockquote>\n"+K+"\n</blockquote>")});return H};var g=function(N){N=N.replace(/^\n+/g,"");N=N.replace(/\n+$/g,"");var M=N.split(/\n{2,}/g);var J=new Array();var H=M.length;for(var I=0;I<H;I++){var L=M[I];if(L.search(/~K(\d+)K/g)>=0){J.push(L)}else{if(L.search(/\S/)>=0){L=r(L);L=L.replace(/^([ \t]*)/g,"<p>");L+="</p>";J.push(L)}}}H=J.length;for(var I=0;I<H;I++){while(J[I].search(/~K(\d+)K/)>=0){var K=A[RegExp.$1];K=K.replace(/\$/g,"$$$$");J[I]=J[I].replace(/~K\d+K/,K)}}return J.join("\n\n")};var h=function(H){H=H.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g,"&amp;");H=H.replace(/<(?![a-z\/?\$!])/gi,"&lt;");return H};var e=function(H){H=H.replace(/\\(\\)/g,k);H=H.replace(/\\([`*_{}\[\]()>#+-.!])/g,k);return H};var n=function(H){H=H.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi,'<a href="$1">$1</a>');H=H.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,function(I,J){return B(q(J))});return H};var B=function(J){function I(L){var K="0123456789ABCDEF";var M=L.charCodeAt(0);return(K.charAt(M>>4)+K.charAt(M&15))}var H=[function(K){return"&#"+K.charCodeAt(0)+";"},function(K){return"&#x"+I(K)+";"},function(K){return K}];J="mailto:"+J;J=J.replace(/./g,function(K){if(K=="@"){K=H[Math.floor(Math.random()*2)](K)}else{if(K!=":"){var L=Math.random();K=(L>0.9?H[2](K):L>0.45?H[1](K):H[0](K))}}return K});J='<a href="'+J+'">'+J+"</a>";J=J.replace(/">.+:/g,'">');return J};var q=function(H){H=H.replace(/~E(\d+)E/g,function(I,K){var J=parseInt(K);return String.fromCharCode(J)});return H};var s=function(H){H=H.replace(/^(\t|[ ]{1,4})/gm,"~0");H=H.replace(/~0/g,"");return H};var z=function(H){H=H.replace(/\t(?=\t)/g,"    ");H=H.replace(/\t/g,"~A~B");H=H.replace(/~B(.+?)~A/g,function(I,L,K){var N=L;var J=4-N.length%4;for(var M=0;M<J;M++){N+=" "}return N});H=H.replace(/~A/g,"    ");H=H.replace(/~B/g,"");return H};var w=function(L,I,J){var H="(["+I.replace(/([\[\]\\])/g,"\\$1")+"])";if(J){H="\\\\"+H}var K=new RegExp(H,"g");L=L.replace(K,k);return L};var k=function(H,J){var I=J.charCodeAt(0);return"~E"+I+"E"}};var Showdown=Attacklab.showdown;if(Attacklab.fileLoaded){Attacklab.fileLoaded("showdown.js")};
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/showdown.js b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/showdown.js
new file mode 100644 (file)
index 0000000..330550d
--- /dev/null
@@ -0,0 +1,1308 @@
+//
+// showdown.js -- A javascript port of Markdown.
+//
+// Copyright (c) 2007 John Fraser.
+//
+// Original Markdown Copyright (c) 2004-2005 John Gruber
+//   <http://daringfireball.net/projects/markdown/>
+//
+// The full source distribution is at:
+//
+//                             A A L
+//                             T C A
+//                             T K B
+//
+//   <http://www.attacklab.net/>
+//
+
+//
+// Wherever possible, Showdown is a straight, line-by-line port
+// of the Perl version of Markdown.
+//
+// This is not a normal parser design; it's basically just a
+// series of string substitutions.  It's hard to read and
+// maintain this way,  but keeping Showdown close to the original
+// design makes it easier to port new features.
+//
+// More importantly, Showdown behaves like markdown.pl in most
+// edge cases.  So web applications can do client-side preview
+// in Javascript, and then build identical HTML on the server.
+//
+// This port needs the new RegExp functionality of ECMA 262,
+// 3rd Edition (i.e. Javascript 1.5).  Most modern web browsers
+// should do fine.  Even with the new regular expression features,
+// We do a lot of work to emulate Perl's regex functionality.
+// The tricky changes in this file mostly have the "attacklab:"
+// label.  Major or self-explanatory changes don't.
+//
+// Smart diff tools like Araxis Merge will be able to match up
+// this file with markdown.pl in a useful way.  A little tweaking
+// helps: in a copy of markdown.pl, replace "#" with "//" and
+// replace "$text" with "text".  Be sure to ignore whitespace
+// and line endings.
+//
+
+
+//
+// Showdown usage:
+//
+//   var text = "Markdown *rocks*.";
+//
+//   var converter = new Attacklab.showdown.converter();
+//   var html = converter.makeHtml(text);
+//
+//   alert(html);
+//
+// Note: move the sample code to the bottom of this
+// file before uncommenting it.
+//
+
+
+//
+// Attacklab namespace
+//
+var Attacklab = Attacklab || {}
+
+//
+// Showdown namespace
+//
+Attacklab.showdown = Attacklab.showdown || {}
+
+//
+// converter
+//
+// Wraps all "globals" so that the only thing
+// exposed is makeHtml().
+//
+Attacklab.showdown.converter = function() {
+
+//
+// Globals:
+//
+
+// Global hashes, used by various utility routines
+var g_urls;
+var g_titles;
+var g_html_blocks;
+
+// Used to track when we're inside an ordered or unordered list
+// (see _ProcessListItems() for details):
+var g_list_level = 0;
+
+
+this.makeHtml = function(text) {
+//
+// Main function. The order in which other subs are called here is
+// essential. Link and image substitutions need to happen before
+// _EscapeSpecialCharsWithinTagAttributes(), so that any *'s or _'s in the <a>
+// and <img> tags get encoded.
+//
+
+       // Clear the global hashes. If we don't clear these, you get conflicts
+       // from other articles when generating a page which contains more than
+       // one article (e.g. an index page that shows the N most recent
+       // articles):
+       g_urls = new Array();
+       g_titles = new Array();
+       g_html_blocks = new Array();
+
+       // attacklab: Replace ~ with ~T
+       // This lets us use tilde as an escape char to avoid md5 hashes
+       // The choice of character is arbitray; anything that isn't
+    // magic in Markdown will work.
+       text = text.replace(/~/g,"~T");
+
+       // attacklab: Replace $ with ~D
+       // RegExp interprets $ as a special character
+       // when it's in a replacement string
+       text = text.replace(/\$/g,"~D");
+
+       // Standardize line endings
+       text = text.replace(/\r\n/g,"\n"); // DOS to Unix
+       text = text.replace(/\r/g,"\n"); // Mac to Unix
+
+       // Make sure text begins and ends with a couple of newlines:
+       text = "\n\n" + text + "\n\n";
+
+       // Convert all tabs to spaces.
+       text = _Detab(text);
+
+       // Strip any lines consisting only of spaces and tabs.
+       // This makes subsequent regexen easier to write, because we can
+       // match consecutive blank lines with /\n+/ instead of something
+       // contorted like /[ \t]*\n+/ .
+       text = text.replace(/^[ \t]+$/mg,"");
+
+       // Turn block-level HTML blocks into hash entries
+       text = _HashHTMLBlocks(text);
+
+       // Strip link definitions, store in hashes.
+       text = _StripLinkDefinitions(text);
+
+       text = _RunBlockGamut(text);
+
+       text = _UnescapeSpecialChars(text);
+
+       // attacklab: Restore dollar signs
+       text = text.replace(/~D/g,"$$");
+
+       // attacklab: Restore tildes
+       text = text.replace(/~T/g,"~");
+
+       return text;
+}
+
+var _StripLinkDefinitions = function(text) {
+//
+// Strips link definitions from text, stores the URLs and titles in
+// hash references.
+//
+
+       // Link defs are in the form: ^[id]: url "optional title"
+
+       /*
+               var text = text.replace(/
+                               ^[ ]{0,3}\[(.+)\]:  // id = $1  attacklab: g_tab_width - 1
+                                 [ \t]*
+                                 \n?                           // maybe *one* newline
+                                 [ \t]*
+                               <?(\S+?)>?                      // url = $2
+                                 [ \t]*
+                                 \n?                           // maybe one newline
+                                 [ \t]*
+                               (?:
+                                 (\n*)                         // any lines skipped = $3 attacklab: lookbehind removed
+                                 ["(]
+                                 (.+?)                         // title = $4
+                                 [")]
+                                 [ \t]*
+                               )?                                      // title is optional
+                               (?:\n+|$)
+                         /gm,
+                         function(){...});
+       */
+       var text = text.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+)/gm,
+               function (wholeMatch,m1,m2,m3,m4) {
+                       m1 = m1.toLowerCase();
+                       g_urls[m1] = _EncodeAmpsAndAngles(m2);  // Link IDs are case-insensitive
+                       if (m3) {
+                               // Oops, found blank lines, so it's not a title.
+                               // Put back the parenthetical statement we stole.
+                               return m3+m4;
+                       } else if (m4) {
+                               g_titles[m1] = m4.replace(/"/g,"&quot;");
+                       }
+                       
+                       // Completely remove the definition from the text
+                       return "";
+               }
+       );
+
+       return text;
+}
+
+var _HashHTMLBlocks = function(text) {
+       // attacklab: Double up blank lines to reduce lookaround
+       text = text.replace(/\n/g,"\n\n");
+
+       // Hashify HTML blocks:
+       // We only want to do this for block-level HTML tags, such as headers,
+       // lists, and tables. That's because we still want to wrap <p>s around
+       // "paragraphs" that are wrapped in non-block-level tags, such as anchors,
+       // phrase emphasis, and spans. The list of tags we're looking for is
+       // hard-coded:
+       var block_tags_a = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del"
+       var block_tags_b = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math"
+
+       // First, look for nested blocks, e.g.:
+       //   <div>
+       //     <div>
+       //     tags for inner block must be indented.
+       //     </div>
+       //   </div>
+       //
+       // The outermost tags must start at the left margin for this to match, and
+       // the inner nested divs must be indented.
+       // We need to do this before the next, more liberal match, because the next
+       // match will start at the first `<div>` and stop at the first `</div>`.
+
+       // attacklab: This regex can be expensive when it fails.
+       /*
+               var text = text.replace(/
+               (                                               // save in $1
+                       ^                                       // start of line  (with /m)
+                       <($block_tags_a)        // start tag = $2
+                       \b                                      // word break
+                                                               // attacklab: hack around khtml/pcre bug...
+                       [^\r]*?\n                       // any number of lines, minimally matching
+                       </\2>                           // the matching end tag
+                       [ \t]*                          // trailing spaces/tabs
+                       (?=\n+)                         // followed by a newline
+               )                                               // attacklab: there are sentinel newlines at end of document
+               /gm,function(){...}};
+       */
+       text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm,hashElement);
+
+       //
+       // Now match more liberally, simply from `\n<tag>` to `</tag>\n`
+       //
+
+       /*
+               var text = text.replace(/
+               (                                               // save in $1
+                       ^                                       // start of line  (with /m)
+                       <($block_tags_b)        // start tag = $2
+                       \b                                      // word break
+                                                               // attacklab: hack around khtml/pcre bug...
+                       [^\r]*?                         // any number of lines, minimally matching
+                       .*</\2>                         // the matching end tag
+                       [ \t]*                          // trailing spaces/tabs
+                       (?=\n+)                         // followed by a newline
+               )                                               // attacklab: there are sentinel newlines at end of document
+               /gm,function(){...}};
+       */
+       text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math)\b[^\r]*?.*<\/\2>[ \t]*(?=\n+)\n)/gm,hashElement);
+
+       // Special case just for <hr />. It was easier to make a special case than
+       // to make the other regex more complicated.  
+
+       /*
+               text = text.replace(/
+               (                                               // save in $1
+                       \n\n                            // Starting after a blank line
+                       [ ]{0,3}
+                       (<(hr)                          // start tag = $2
+                       \b                                      // word break
+                       ([^<>])*?                       // 
+                       \/?>)                           // the matching end tag
+                       [ \t]*
+                       (?=\n{2,})                      // followed by a blank line
+               )
+               /g,hashElement);
+       */
+       text = text.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,hashElement);
+
+       // Special case for standalone HTML comments:
+
+       /*
+               text = text.replace(/
+               (                                               // save in $1
+                       \n\n                            // Starting after a blank line
+                       [ ]{0,3}                        // attacklab: g_tab_width - 1
+                       <!
+                       (--[^\r]*?--\s*)+
+                       >
+                       [ \t]*
+                       (?=\n{2,})                      // followed by a blank line
+               )
+               /g,hashElement);
+       */
+       text = text.replace(/(\n\n[ ]{0,3}<!(--[^\r]*?--\s*)+>[ \t]*(?=\n{2,}))/g,hashElement);
+
+       // PHP and ASP-style processor instructions (<?...?> and <%...%>)
+
+       /*
+               text = text.replace(/
+               (?:
+                       \n\n                            // Starting after a blank line
+               )
+               (                                               // save in $1
+                       [ ]{0,3}                        // attacklab: g_tab_width - 1
+                       (?:
+                               <([?%])                 // $2
+                               [^\r]*?
+                               \2>
+                       )
+                       [ \t]*
+                       (?=\n{2,})                      // followed by a blank line
+               )
+               /g,hashElement);
+       */
+       text = text.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,hashElement);
+
+       // attacklab: Undo double lines (see comment at top of this function)
+       text = text.replace(/\n\n/g,"\n");
+       return text;
+}
+
+var hashElement = function(wholeMatch,m1) {
+       var blockText = m1;
+
+       // Undo double lines
+       blockText = blockText.replace(/\n\n/g,"\n");
+       blockText = blockText.replace(/^\n/,"");
+       
+       // strip trailing blank lines
+       blockText = blockText.replace(/\n+$/g,"");
+       
+       // Replace the element text with a marker ("~KxK" where x is its key)
+       blockText = "\n\n~K" + (g_html_blocks.push(blockText)-1) + "K\n\n";
+       
+       return blockText;
+};
+
+var _RunBlockGamut = function(text) {
+//
+// These are all the transformations that form block-level
+// tags like paragraphs, headers, and list items.
+//
+       text = _DoHeaders(text);
+
+       // Do Horizontal Rules:
+       var key = hashBlock("<hr />");
+       text = text.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm,key);
+       text = text.replace(/^[ ]{0,2}([ ]?-[ ]?){3,}[ \t]*$/gm,key);
+       text = text.replace(/^[ ]{0,2}([ ]?_[ ]?){3,}[ \t]*$/gm,key);
+
+       text = _DoLists(text);
+       text = _DoCodeBlocks(text);
+       text = _DoBlockQuotes(text);
+
+       // We already ran _HashHTMLBlocks() before, in Markdown(), but that
+       // was to escape raw HTML in the original Markdown source. This time,
+       // we're escaping the markup we've just created, so that we don't wrap
+       // <p> tags around block-level tags.
+       text = _HashHTMLBlocks(text);
+       text = _FormParagraphs(text);
+
+       return text;
+}
+
+
+var _RunSpanGamut = function(text) {
+//
+// These are all the transformations that occur *within* block-level
+// tags like paragraphs, headers, and list items.
+//
+
+       text = _DoCodeSpans(text);
+       text = _EscapeSpecialCharsWithinTagAttributes(text);
+       text = _EncodeBackslashEscapes(text);
+
+       // Process anchor and image tags. Images must come first,
+       // because ![foo][f] looks like an anchor.
+       text = _DoImages(text);
+       text = _DoAnchors(text);
+
+       // Make links out of things like `<http://example.com/>`
+       // Must come after _DoAnchors(), because you can use < and >
+       // delimiters in inline links like [this](<url>).
+       text = _DoAutoLinks(text);
+       text = _EncodeAmpsAndAngles(text);
+       text = _DoItalicsAndBold(text);
+
+       // Do hard breaks:
+       text = text.replace(/  +\n/g," <br />\n");
+
+       return text;
+}
+
+var _EscapeSpecialCharsWithinTagAttributes = function(text) {
+//
+// Within tags -- meaning between < and > -- encode [\ ` * _] so they
+// don't conflict with their use in Markdown for code, italics and strong.
+//
+
+       // Build a regex to find HTML tags and comments.  See Friedl's 
+       // "Mastering Regular Expressions", 2nd Ed., pp. 200-201.
+       var regex = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--.*?--\s*)+>)/gi;
+
+       text = text.replace(regex, function(wholeMatch) {
+               var tag = wholeMatch.replace(/(.)<\/?code>(?=.)/g,"$1`");
+               tag = escapeCharacters(tag,"\\`*_");
+               return tag;
+       });
+
+       return text;
+}
+
+var _DoAnchors = function(text) {
+//
+// Turn Markdown link shortcuts into XHTML <a> tags.
+//
+       //
+       // First, handle reference-style links: [link text] [id]
+       //
+
+       /*
+               text = text.replace(/
+               (                                                       // wrap whole match in $1
+                       \[
+                       (
+                               (?:
+                                       \[[^\]]*\]              // allow brackets nested one level
+                                       |
+                                       [^\[]                   // or anything else
+                               )*
+                       )
+                       \]
+
+                       [ ]?                                    // one optional space
+                       (?:\n[ ]*)?                             // one optional newline followed by spaces
+
+                       \[
+                       (.*?)                                   // id = $3
+                       \]
+               )()()()()                                       // pad remaining backreferences
+               /g,_DoAnchors_callback);
+       */
+       text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,writeAnchorTag);
+
+       //
+       // Next, inline-style links: [link text](url "optional title")
+       //
+
+       /*
+               text = text.replace(/
+                       (                                               // wrap whole match in $1
+                               \[
+                               (
+                                       (?:
+                                               \[[^\]]*\]      // allow brackets nested one level
+                                       |
+                                       [^\[\]]                 // or anything else
+                               )
+                       )
+                       \]
+                       \(                                              // literal paren
+                       [ \t]*
+                       ()                                              // no id, so leave $3 empty
+                       <?(.*?)>?                               // href = $4
+                       [ \t]*
+                       (                                               // $5
+                               (['"])                          // quote char = $6
+                               (.*?)                           // Title = $7
+                               \6                                      // matching quote
+                               [ \t]*                          // ignore any spaces/tabs between closing quote and )
+                       )?                                              // title is optional
+                       \)
+               )
+               /g,writeAnchorTag);
+       */
+       text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()<?(.*?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,writeAnchorTag);
+
+       //
+       // Last, handle reference-style shortcuts: [link text]
+       // These must come last in case you've also got [link test][1]
+       // or [link test](/foo)
+       //
+
+       /*
+               text = text.replace(/
+               (                                                       // wrap whole match in $1
+                       \[
+                       ([^\[\]]+)                              // link text = $2; can't contain '[' or ']'
+                       \]
+               )()()()()()                                     // pad rest of backreferences
+               /g, writeAnchorTag);
+       */
+       text = text.replace(/(\[([^\[\]]+)\])()()()()()/g, writeAnchorTag);
+
+       return text;
+}
+
+var writeAnchorTag = function(wholeMatch,m1,m2,m3,m4,m5,m6,m7) {
+       if (m7 == undefined) m7 = "";
+       var whole_match = m1;
+       var link_text   = m2;
+       var link_id      = m3.toLowerCase();
+       var url         = m4;
+       var title       = m7;
+       
+       if (url == "") {
+               if (link_id == "") {
+                       // lower-case and turn embedded newlines into spaces
+                       link_id = link_text.toLowerCase().replace(/ ?\n/g," ");
+               }
+               url = "#"+link_id;
+               
+               if (g_urls[link_id] != undefined) {
+                       url = g_urls[link_id];
+                       if (g_titles[link_id] != undefined) {
+                               title = g_titles[link_id];
+                       }
+               }
+               else {
+                       if (whole_match.search(/\(\s*\)$/m)>-1) {
+                               // Special case for explicit empty url
+                               url = "";
+                       } else {
+                               return whole_match;
+                       }
+               }
+       }       
+       
+       url = escapeCharacters(url,"*_");
+       var result = "<a href=\"" + url + "\"";
+       
+       if (title != "") {
+               title = title.replace(/"/g,"&quot;");
+               title = escapeCharacters(title,"*_");
+               result +=  " title=\"" + title + "\"";
+       }
+       
+       result += ">" + link_text + "</a>";
+       
+       return result;
+}
+
+
+var _DoImages = function(text) {
+//
+// Turn Markdown image shortcuts into <img> tags.
+//
+
+       //
+       // First, handle reference-style labeled images: ![alt text][id]
+       //
+
+       /*
+               text = text.replace(/
+               (                                               // wrap whole match in $1
+                       !\[
+                       (.*?)                           // alt text = $2
+                       \]
+
+                       [ ]?                            // one optional space
+                       (?:\n[ ]*)?                     // one optional newline followed by spaces
+
+                       \[
+                       (.*?)                           // id = $3
+                       \]
+               )()()()()                               // pad rest of backreferences
+               /g,writeImageTag);
+       */
+       text = text.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,writeImageTag);
+
+       //
+       // Next, handle inline images:  ![alt text](url "optional title")
+       // Don't forget: encode * and _
+
+       /*
+               text = text.replace(/
+               (                                               // wrap whole match in $1
+                       !\[
+                       (.*?)                           // alt text = $2
+                       \]
+                       \s?                                     // One optional whitespace character
+                       \(                                      // literal paren
+                       [ \t]*
+                       ()                                      // no id, so leave $3 empty
+                       <?(\S+?)>?                      // src url = $4
+                       [ \t]*
+                       (                                       // $5
+                               (['"])                  // quote char = $6
+                               (.*?)                   // title = $7
+                               \6                              // matching quote
+                               [ \t]*
+                       )?                                      // title is optional
+               \)
+               )
+               /g,writeImageTag);
+       */
+       text = text.replace(/(!\[(.*?)\]\s?\([ \t]*()<?(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,writeImageTag);
+
+       return text;
+}
+
+var writeImageTag = function(wholeMatch,m1,m2,m3,m4,m5,m6,m7) {
+       var whole_match = m1;
+       var alt_text   = m2;
+       var link_id      = m3.toLowerCase();
+       var url         = m4;
+       var title       = m7;
+
+       if (!title) title = "";
+       
+       if (url == "") {
+               if (link_id == "") {
+                       // lower-case and turn embedded newlines into spaces
+                       link_id = alt_text.toLowerCase().replace(/ ?\n/g," ");
+               }
+               url = "#"+link_id;
+               
+               if (g_urls[link_id] != undefined) {
+                       url = g_urls[link_id];
+                       if (g_titles[link_id] != undefined) {
+                               title = g_titles[link_id];
+                       }
+               }
+               else {
+                       return whole_match;
+               }
+       }       
+       
+       alt_text = alt_text.replace(/"/g,"&quot;");
+       url = escapeCharacters(url,"*_");
+       url = scriptUrl + url
+       var result = "<img src=\"" + url + "\" alt=\"" + alt_text + "\"";
+       result = result.replace("//", "/")
+
+       // attacklab: Markdown.pl adds empty title attributes to images.
+       // Replicate this bug.
+
+       //if (title != "") {
+               title = title.replace(/"/g,"&quot;");
+               title = escapeCharacters(title,"*_");
+               result +=  " title=\"" + title + "\"";
+       //}
+       
+       result += " />";
+       
+       return result;
+}
+
+
+var _DoHeaders = function(text) {
+
+       // Setext-style headers:
+       //      Header 1
+       //      ========
+       //  
+       //      Header 2
+       //      --------
+       //
+       text = text.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm,
+               function(wholeMatch,m1){return hashBlock("<h1>" + _RunSpanGamut(m1) + "</h1>");});
+
+       text = text.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm,
+               function(matchFound,m1){return hashBlock("<h2>" + _RunSpanGamut(m1) + "</h2>");});
+
+       // atx-style headers:
+       //  # Header 1
+       //  ## Header 2
+       //  ## Header 2 with closing hashes ##
+       //  ...
+       //  ###### Header 6
+       //
+
+       /*
+               text = text.replace(/
+                       ^(\#{1,6})                              // $1 = string of #'s
+                       [ \t]*
+                       (.+?)                                   // $2 = Header text
+                       [ \t]*
+                       \#*                                             // optional closing #'s (not counted)
+                       \n+
+               /gm, function() {...});
+       */
+
+       text = text.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm,
+               function(wholeMatch,m1,m2) {
+                       var h_level = m1.length;
+                       return hashBlock("<h" + h_level + ">" + _RunSpanGamut(m2) + "</h" + h_level + ">");
+               });
+
+       return text;
+}
+
+// This declaration keeps Dojo compressor from outputting garbage:
+var _ProcessListItems;
+
+var _DoLists = function(text) {
+//
+// Form HTML ordered (numbered) and unordered (bulleted) lists.
+//
+
+       // attacklab: add sentinel to hack around khtml/safari bug:
+       // http://bugs.webkit.org/show_bug.cgi?id=11231
+       text += "~0";
+
+       // Re-usable pattern to match any entirel ul or ol list:
+
+       /*
+               var whole_list = /
+               (                                                                       // $1 = whole list
+                       (                                                               // $2
+                               [ ]{0,3}                                        // attacklab: g_tab_width - 1
+                               ([*+-]|\d+[.])                          // $3 = first list item marker
+                               [ \t]+
+                       )
+                       [^\r]+?
+                       (                                                               // $4
+                               ~0                                                      // sentinel for workaround; should be $
+                       |
+                               \n{2,}
+                               (?=\S)
+                               (?!                                                     // Negative lookahead for another list item marker
+                                       [ \t]*
+                                       (?:[*+-]|\d+[.])[ \t]+
+                               )
+                       )
+               )/g
+       */
+       var whole_list = /^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm;
+
+       if (g_list_level) {
+               text = text.replace(whole_list,function(wholeMatch,m1,m2) {
+                       var list = m1;
+                       var list_type = (m2.search(/[*+-]/g)>-1) ? "ul" : "ol";
+
+                       // Turn double returns into triple returns, so that we can make a
+                       // paragraph for the last item in a list, if necessary:
+                       list = list.replace(/\n{2,}/g,"\n\n\n");;
+                       var result = _ProcessListItems(list);
+       
+                       // Trim any trailing whitespace, to put the closing `</$list_type>`
+                       // up on the preceding line, to get it past the current stupid
+                       // HTML block parser. This is a hack to work around the terrible
+                       // hack that is the HTML block parser.
+                       result = result.replace(/\s+$/,"");
+                       result = "<"+list_type+">" + result + "</"+list_type+">\n";
+                       return result;
+               });
+       } else {
+               whole_list = /(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g;
+               text = text.replace(whole_list,function(wholeMatch,m1,m2,m3) {
+                       var runup = m1;
+                       var list = m2;
+
+                       var list_type = (m3.search(/[*+-]/g)>-1) ? "ul" : "ol";
+                       // Turn double returns into triple returns, so that we can make a
+                       // paragraph for the last item in a list, if necessary:
+                       var list = list.replace(/\n{2,}/g,"\n\n\n");;
+                       var result = _ProcessListItems(list);
+                       result = runup + "<"+list_type+">\n" + result + "</"+list_type+">\n";   
+                       return result;
+               });
+       }
+
+       // attacklab: strip sentinel
+       text = text.replace(/~0/,"");
+
+       return text;
+}
+
+_ProcessListItems = function(list_str) {
+//
+//  Process the contents of a single ordered or unordered list, splitting it
+//  into individual list items.
+//
+       // The $g_list_level global keeps track of when we're inside a list.
+       // Each time we enter a list, we increment it; when we leave a list,
+       // we decrement. If it's zero, we're not in a list anymore.
+       //
+       // We do this because when we're not inside a list, we want to treat
+       // something like this:
+       //
+       //    I recommend upgrading to version
+       //    8. Oops, now this line is treated
+       //    as a sub-list.
+       //
+       // As a single paragraph, despite the fact that the second line starts
+       // with a digit-period-space sequence.
+       //
+       // Whereas when we're inside a list (or sub-list), that line will be
+       // treated as the start of a sub-list. What a kludge, huh? This is
+       // an aspect of Markdown's syntax that's hard to parse perfectly
+       // without resorting to mind-reading. Perhaps the solution is to
+       // change the syntax rules such that sub-lists must start with a
+       // starting cardinal number; e.g. "1." or "a.".
+
+       g_list_level++;
+
+       // trim trailing blank lines:
+       list_str = list_str.replace(/\n{2,}$/,"\n");
+
+       // attacklab: add sentinel to emulate \z
+       list_str += "~0";
+
+       /*
+               list_str = list_str.replace(/
+                       (\n)?                                                   // leading line = $1
+                       (^[ \t]*)                                               // leading whitespace = $2
+                       ([*+-]|\d+[.]) [ \t]+                   // list marker = $3
+                       ([^\r]+?                                                // list item text   = $4
+                       (\n{1,2}))
+                       (?= \n* (~0 | \2 ([*+-]|\d+[.]) [ \t]+))
+               /gm, function(){...});
+       */
+       list_str = list_str.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm,
+               function(wholeMatch,m1,m2,m3,m4){
+                       var item = m4;
+                       var leading_line = m1;
+                       var leading_space = m2;
+
+                       if (leading_line || (item.search(/\n{2,}/)>-1)) {
+                               item = _RunBlockGamut(_Outdent(item));
+                       }
+                       else {
+                               // Recursion for sub-lists:
+                               item = _DoLists(_Outdent(item));
+                               item = item.replace(/\n$/,""); // chomp(item)
+                               item = _RunSpanGamut(item);
+                       }
+
+                       return  "<li>" + item + "</li>\n";
+               }
+       );
+
+       // attacklab: strip sentinel
+       list_str = list_str.replace(/~0/g,"");
+
+       g_list_level--;
+       return list_str;
+}
+
+
+var _DoCodeBlocks = function(text) {
+//
+//  Process Markdown `<pre><code>` blocks.
+//  
+
+       /*
+               text = text.replace(text,
+                       /(?:\n\n|^)
+                       (                                                               // $1 = the code block -- one or more lines, starting with a space/tab
+                               (?:
+                                       (?:[ ]{4}|\t)                   // Lines must start with a tab or a tab-width of spaces - attacklab: g_tab_width
+                                       .*\n+
+                               )+
+                       )
+                       (\n*[ ]{0,3}[^ \t\n]|(?=~0))    // attacklab: g_tab_width
+               /g,function(){...});
+       */
+
+       // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
+       text += "~0";
+       
+       text = text.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g,
+               function(wholeMatch,m1,m2) {
+                       var codeblock = m1;
+                       var nextChar = m2;
+               
+                       codeblock = _EncodeCode( _Outdent(codeblock));
+                       codeblock = _Detab(codeblock);
+                       codeblock = codeblock.replace(/^\n+/g,""); // trim leading newlines
+                       codeblock = codeblock.replace(/\n+$/g,""); // trim trailing whitespace
+
+                       codeblock = "<pre><code>" + codeblock + "\n</code></pre>";
+
+                       return hashBlock(codeblock) + nextChar;
+               }
+       );
+
+       // attacklab: strip sentinel
+       text = text.replace(/~0/,"");
+
+       return text;
+}
+
+var hashBlock = function(text) {
+       text = text.replace(/(^\n+|\n+$)/g,"");
+       return "\n\n~K" + (g_html_blocks.push(text)-1) + "K\n\n";
+}
+
+
+var _DoCodeSpans = function(text) {
+//
+//   *  Backtick quotes are used for <code></code> spans.
+// 
+//   *  You can use multiple backticks as the delimiters if you want to
+//      include literal backticks in the code span. So, this input:
+//      
+//              Just type ``foo `bar` baz`` at the prompt.
+//      
+//        Will translate to:
+//      
+//              <p>Just type <code>foo `bar` baz</code> at the prompt.</p>
+//      
+//     There's no arbitrary limit to the number of backticks you
+//     can use as delimters. If you need three consecutive backticks
+//     in your code, use four for delimiters, etc.
+//
+//  *  You can use spaces to get literal backticks at the edges:
+//      
+//              ... type `` `bar` `` ...
+//      
+//        Turns to:
+//      
+//              ... type <code>`bar`</code> ...
+//
+
+       /*
+               text = text.replace(/
+                       (^|[^\\])                                       // Character before opening ` can't be a backslash
+                       (`+)                                            // $2 = Opening run of `
+                       (                                                       // $3 = The code block
+                               [^\r]*?
+                               [^`]                                    // attacklab: work around lack of lookbehind
+                       )
+                       \2                                                      // Matching closer
+                       (?!`)
+               /gm, function(){...});
+       */
+
+       text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,
+               function(wholeMatch,m1,m2,m3,m4) {
+                       var c = m3;
+                       c = c.replace(/^([ \t]*)/g,""); // leading whitespace
+                       c = c.replace(/[ \t]*$/g,"");   // trailing whitespace
+                       c = _EncodeCode(c);
+                       return m1+"<code>"+c+"</code>";
+               });
+
+       return text;
+}
+
+
+var _EncodeCode = function(text) {
+//
+// Encode/escape certain characters inside Markdown code runs.
+// The point is that in code, these characters are literals,
+// and lose their special Markdown meanings.
+//
+       // Encode all ampersands; HTML entities are not
+       // entities within a Markdown code span.
+       text = text.replace(/&/g,"&amp;");
+
+       // Do the angle bracket song and dance:
+       text = text.replace(/</g,"&lt;");
+       text = text.replace(/>/g,"&gt;");
+
+       // Now, escape characters that are magic in Markdown:
+       text = escapeCharacters(text,"\*_{}[]\\",false);
+
+// jj the line above breaks this:
+//---
+
+//* Item
+
+//   1. Subitem
+
+//            special char: *
+//---
+
+       return text;
+}
+
+
+var _DoItalicsAndBold = function(text) {
+
+       // <strong> must go first:
+       text = text.replace(/(\*\*|__)(?=\S)([^\r]*?\S[\*_]*)\1/g,
+               "<strong>$2</strong>");
+
+       text = text.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g,
+               "<em>$2</em>");
+
+       return text;
+}
+
+
+var _DoBlockQuotes = function(text) {
+
+       /*
+               text = text.replace(/
+               (                                                               // Wrap whole match in $1
+                       (
+                               ^[ \t]*>[ \t]?                  // '>' at the start of a line
+                               .+\n                                    // rest of the first line
+                               (.+\n)*                                 // subsequent consecutive lines
+                               \n*                                             // blanks
+                       )+
+               )
+               /gm, function(){...});
+       */
+
+       text = text.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm,
+               function(wholeMatch,m1) {
+                       var bq = m1;
+
+                       // attacklab: hack around Konqueror 3.5.4 bug:
+                       // "----------bug".replace(/^-/g,"") == "bug"
+
+                       bq = bq.replace(/^[ \t]*>[ \t]?/gm,"~0");       // trim one level of quoting
+
+                       // attacklab: clean up hack
+                       bq = bq.replace(/~0/g,"");
+
+                       bq = bq.replace(/^[ \t]+$/gm,"");               // trim whitespace-only lines
+                       bq = _RunBlockGamut(bq);                                // recurse
+                       
+                       bq = bq.replace(/(^|\n)/g,"$1  ");
+                       // These leading spaces screw with <pre> content, so we need to fix that:
+                       bq = bq.replace(
+                                       /(\s*<pre>[^\r]+?<\/pre>)/gm,
+                               function(wholeMatch,m1) {
+                                       var pre = m1;
+                                       // attacklab: hack around Konqueror 3.5.4 bug:
+                                       pre = pre.replace(/^  /mg,"~0");
+                                       pre = pre.replace(/~0/g,"");
+                                       return pre;
+                               });
+                       
+                       return hashBlock("<blockquote>\n" + bq + "\n</blockquote>");
+               });
+       return text;
+}
+
+
+var _FormParagraphs = function(text) {
+//
+//  Params:
+//    $text - string to process with html <p> tags
+//
+
+       // Strip leading and trailing lines:
+       text = text.replace(/^\n+/g,"");
+       text = text.replace(/\n+$/g,"");
+
+       var grafs = text.split(/\n{2,}/g);
+       var grafsOut = new Array();
+
+       //
+       // Wrap <p> tags.
+       //
+       var end = grafs.length;
+       for (var i=0; i<end; i++) {
+               var str = grafs[i];
+
+               // if this is an HTML marker, copy it
+               if (str.search(/~K(\d+)K/g) >= 0) {
+                       grafsOut.push(str);
+               }
+               else if (str.search(/\S/) >= 0) {
+                       str = _RunSpanGamut(str);
+                       str = str.replace(/^([ \t]*)/g,"<p>");
+                       str += "</p>"
+                       grafsOut.push(str);
+               }
+
+       }
+
+       //
+       // Unhashify HTML blocks
+       //
+       end = grafsOut.length;
+       for (var i=0; i<end; i++) {
+               // if this is a marker for an html block...
+               while (grafsOut[i].search(/~K(\d+)K/) >= 0) {
+                       var blockText = g_html_blocks[RegExp.$1];
+                       blockText = blockText.replace(/\$/g,"$$$$"); // Escape any dollar signs
+                       grafsOut[i] = grafsOut[i].replace(/~K\d+K/,blockText);
+               }
+       }
+
+       return grafsOut.join("\n\n");
+}
+
+
+var _EncodeAmpsAndAngles = function(text) {
+// Smart processing for ampersands and angle brackets that need to be encoded.
+       
+       // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin:
+       //   http://bumppo.net/projects/amputator/
+       text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g,"&amp;");
+       
+       // Encode naked <'s
+       text = text.replace(/<(?![a-z\/?\$!])/gi,"&lt;");
+       
+       return text;
+}
+
+
+var _EncodeBackslashEscapes = function(text) {
+//
+//   Parameter:  String.
+//   Returns:  The string, with after processing the following backslash
+//                        escape sequences.
+//
+
+       // attacklab: The polite way to do this is with the new
+       // escapeCharacters() function:
+       //
+       //      text = escapeCharacters(text,"\\",true);
+       //      text = escapeCharacters(text,"`*_{}[]()>#+-.!",true);
+       //
+       // ...but we're sidestepping its use of the (slow) RegExp constructor
+       // as an optimization for Firefox.  This function gets called a LOT.
+
+       text = text.replace(/\\(\\)/g,escapeCharacters_callback);
+       text = text.replace(/\\([`*_{}\[\]()>#+-.!])/g,escapeCharacters_callback);
+       return text;
+}
+
+
+var _DoAutoLinks = function(text) {
+
+       text = text.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi,"<a href=\"$1\">$1</a>");
+
+       // Email addresses: <address@domain.foo>
+
+       /*
+               text = text.replace(/
+                       <
+                       (?:mailto:)?
+                       (
+                               [-.\w]+
+                               \@
+                               [-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+
+                       )
+                       >
+               /gi, _DoAutoLinks_callback());
+       */
+       text = text.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,
+               function(wholeMatch,m1) {
+                       return _EncodeEmailAddress( _UnescapeSpecialChars(m1) );
+               }
+       );
+
+       return text;
+}
+
+
+var _EncodeEmailAddress = function(addr) {
+//
+//  Input: an email address, e.g. "foo@example.com"
+//
+//  Output: the email address as a mailto link, with each character
+//     of the address encoded as either a decimal or hex entity, in
+//     the hopes of foiling most address harvesting spam bots. E.g.:
+//
+//     <a href="&#x6D;&#97;&#105;&#108;&#x74;&#111;:&#102;&#111;&#111;&#64;&#101;
+//        x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;">&#102;&#111;&#111;
+//        &#64;&#101;x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;</a>
+//
+//  Based on a filter by Matthew Wickline, posted to the BBEdit-Talk
+//  mailing list: <http://tinyurl.com/yu7ue>
+//
+
+       // attacklab: why can't javascript speak hex?
+       function char2hex(ch) {
+               var hexDigits = '0123456789ABCDEF';
+               var dec = ch.charCodeAt(0);
+               return(hexDigits.charAt(dec>>4) + hexDigits.charAt(dec&15));
+       }
+
+       var encode = [
+               function(ch){return "&#"+ch.charCodeAt(0)+";";},
+               function(ch){return "&#x"+char2hex(ch)+";";},
+               function(ch){return ch;}
+       ];
+
+       addr = "mailto:" + addr;
+
+       addr = addr.replace(/./g, function(ch) {
+               if (ch == "@") {
+                       // this *must* be encoded. I insist.
+                       ch = encode[Math.floor(Math.random()*2)](ch);
+               } else if (ch !=":") {
+                       // leave ':' alone (to spot mailto: later)
+                       var r = Math.random();
+                       // roughly 10% raw, 45% hex, 45% dec
+                       ch =  (
+                                       r > .9  ?       encode[2](ch)   :
+                                       r > .45 ?       encode[1](ch)   :
+                                                               encode[0](ch)
+                               );
+               }
+               return ch;
+       });
+
+       addr = "<a href=\"" + addr + "\">" + addr + "</a>";
+       addr = addr.replace(/">.+:/g,"\">"); // strip the mailto: from the visible part
+
+       return addr;
+}
+
+
+var _UnescapeSpecialChars = function(text) {
+//
+// Swap back in all the special characters we've hidden.
+//
+       text = text.replace(/~E(\d+)E/g,
+               function(wholeMatch,m1) {
+                       var charCodeToReplace = parseInt(m1);
+                       return String.fromCharCode(charCodeToReplace);
+               }
+       );
+       return text;
+}
+
+
+var _Outdent = function(text) {
+//
+// Remove one level of line-leading tabs or spaces
+//
+
+       // attacklab: hack around Konqueror 3.5.4 bug:
+       // "----------bug".replace(/^-/g,"") == "bug"
+
+       text = text.replace(/^(\t|[ ]{1,4})/gm,"~0"); // attacklab: g_tab_width
+
+       // attacklab: clean up hack
+       text = text.replace(/~0/g,"")
+
+       return text;
+}
+
+var _Detab = function(text) {
+// attacklab: Detab's completely rewritten for speed.
+// In perl we could fix it by anchoring the regexp with \G.
+// In javascript we're less fortunate.
+
+       // expand first n-1 tabs
+       text = text.replace(/\t(?=\t)/g,"    "); // attacklab: g_tab_width
+
+       // replace the nth with two sentinels
+       text = text.replace(/\t/g,"~A~B");
+
+       // use the sentinel to anchor our regex so it doesn't explode
+       text = text.replace(/~B(.+?)~A/g,
+               function(wholeMatch,m1,m2) {
+                       var leadingText = m1;
+                       var numSpaces = 4 - leadingText.length % 4;  // attacklab: g_tab_width
+
+                       // there *must* be a better way to do this:
+                       for (var i=0; i<numSpaces; i++) leadingText+=" ";
+
+                       return leadingText;
+               }
+       );
+
+       // clean up sentinels
+       text = text.replace(/~A/g,"    ");  // attacklab: g_tab_width
+       text = text.replace(/~B/g,"");
+
+       return text;
+}
+
+
+//
+//  attacklab: Utility functions
+//
+
+
+var escapeCharacters = function(text, charsToEscape, afterBackslash) {
+       // First we have to escape the escape characters so that
+       // we can build a character class out of them
+       var regexString = "([" + charsToEscape.replace(/([\[\]\\])/g,"\\$1") + "])";
+
+       if (afterBackslash) {
+               regexString = "\\\\" + regexString;
+       }
+
+       var regex = new RegExp(regexString,"g");
+       text = text.replace(regex,escapeCharacters_callback);
+
+       return text;
+}
+
+
+var escapeCharacters_callback = function(wholeMatch,m1) {
+       var charCodeToEscape = m1.charCodeAt(0);
+       return "~E"+charCodeToEscape+"E";
+}
+
+} // end of Attacklab.showdown.converter
+
+
+// Version 0.9 used the Showdown namespace instead of Attacklab.showdown
+// The old namespace is deprecated, but we'll support it for now:
+var Showdown = Attacklab.showdown;
+
+// If anyone's interested, tell the world that this file's been loaded
+if (Attacklab.fileLoaded) {
+       Attacklab.fileLoaded("showdown.js");
+}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/wmd-min.js b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/wmd-min.js
new file mode 100644 (file)
index 0000000..aa643f1
--- /dev/null
@@ -0,0 +1 @@
+var Attacklab=Attacklab||{};Attacklab.wmdBase=function(){var y=top.Attacklab;var E=top.document;var s=top.RegExp;var l=top.navigator;y.Util={};y.Position={};y.Command={};y.Global={};var a=y.Util;var C=y.Position;var h=y.Command;var v=y.Global;v.isIE=/msie/.test(l.userAgent.toLowerCase());v.isIE_5or6=/msie 6/.test(l.userAgent.toLowerCase())||/msie 5/.test(l.userAgent.toLowerCase());v.isIE_7plus=v.isIE&&!v.isIE_5or6;v.isOpera=/opera/.test(l.userAgent.toLowerCase());v.isKonqueror=/konqueror/.test(l.userAgent.toLowerCase());var c="粗体 <strong> Ctrl-B";var f="斜体 <em> Ctrl-I";var z="超链接 <a> Ctrl-L";var u="引用 <blockquote> Ctrl-.";var e="代码 <pre><code> Ctrl-K";var d="图片 <img> Ctrl-G";var q="数字编号列表 <ol> Ctrl-O";var t="项目符号列表 <ul> Ctrl-U";var i="标题 <h1>/<h2> Ctrl-H";var p="水平线 <hr> Ctrl-R";var m="撤销 Ctrl-Z";var j="重做 Ctrl-Y";var B="<p style='margin-top: 0px'><b>输入图片地址</b></p><p>示例:<br />http://www.cnprog.com/images/temp.jpg   \"我的截图\"</p>";var D="<p style='margin-top: 0px'><b>输入Web地址</b></p><p>示例:<br />http://www.cnprog.com/   \"我的网站\"</p>";var n='<div>或者上传本地图片:</div><input type="file" name="file-upload" id="file-upload" size="26" onchange="return ajaxFileUpload($(\'#image-url\'));"/><br><img id="loading" src="/media/images/indicator.gif" style="display:none;"/>';var b="http://";var g="http://";var o="images/";var A=500;var x=100;var k="http://wmd-editor.com/";var r="WMD website";var w="_blank";y.PanelCollection=function(){this.buttonBar=E.getElementById("wmd-button-bar");this.preview=E.getElementById("previewer");this.output=E.getElementById("wmd-output");this.input=E.getElementById("editor")};y.panels=undefined;y.ieCachedRange=null;y.ieRetardedClick=false;a.isVisible=function(F){if(window.getComputedStyle){return window.getComputedStyle(F,null).getPropertyValue("display")!=="none"}else{if(F.currentStyle){return F.currentStyle.display!=="none"}}};a.addEvent=function(G,F,H){if(G.attachEvent){G.attachEvent("on"+F,H)}else{G.addEventListener(F,H,false)}};a.removeEvent=function(G,F,H){if(G.detachEvent){G.detachEvent("on"+F,H)}else{G.removeEventListener(F,H,false)}};a.fixEolChars=function(F){F=F.replace(/\r\n/g,"\n");F=F.replace(/\r/g,"\n");return F};a.extendRegExp=function(H,J,G){if(J===null||J===undefined){J=""}if(G===null||G===undefined){G=""}var I=H.toString();var F;I=I.replace(/\/([gim]*)$/,"");F=s.$1;I=I.replace(/(^\/|\/$)/g,"");I=J+I+G;return new s(I,F)};a.createImage=function(F){var H=o+F;var G=E.createElement("img");G.className="wmd-button";G.src=H;return G};a.prompt=function(M,P,H){var I;var F;var K;var J=0;if(arguments.length==4){J=arguments[3]}if(P===undefined){P=""}var L=function(Q){var R=(Q.charCode||Q.keyCode);if(R===27){N(true)}};var N=function(Q){a.removeEvent(E.body,"keydown",L);var R=K.value;if(Q){R=null}else{R=R.replace("http://http://","http://");R=R.replace("http://https://","https://");R=R.replace("http://ftp://","ftp://");if(R.indexOf("http://")===-1&&R.indexOf("ftp://")===-1){R="http://"+R}}I.parentNode.removeChild(I);F.parentNode.removeChild(F);H(R);return false};var G=function(){F=E.createElement("div");F.className="wmd-prompt-background";style=F.style;style.position="absolute";style.top="0";style.zIndex="1000";if(v.isKonqueror){style.backgroundColor="transparent"}else{if(v.isIE){style.filter="alpha(opacity=50)"}else{style.opacity="0.5"}}var Q=C.getPageSize();style.height=Q[1]+"px";if(v.isIE){style.left=E.documentElement.scrollLeft;style.width=E.documentElement.clientWidth}else{style.left="0";style.width="100%"}E.body.appendChild(F)};var O=function(){I=E.createElement("div");I.className="wmd-prompt-dialog";I.style.padding="10px;";I.style.position="fixed";I.style.width="400px";I.style.zIndex="1001";var Q=E.createElement("div");Q.innerHTML=M;Q.style.padding="5px";I.appendChild(Q);var S=E.createElement("form");S.onsubmit=function(){return N(false)};style=S.style;style.padding="0";style.margin="0";style.cssFloat="left";style.width="100%";style.textAlign="center";style.position="relative";I.appendChild(S);K=E.createElement("input");if(J==1){K.id="image-url"}K.type="text";K.value=P;style=K.style;style.display="block";style.width="80%";style.marginLeft=style.marginRight="auto";S.appendChild(K);if(J==1){var R=E.createElement("div");R.innerHTML=n;R.style.padding="5px";S.appendChild(R)}var U=E.createElement("input");U.type="button";U.onclick=function(){return N(false)};U.value="OK";style=U.style;style.margin="10px";style.display="inline";style.width="7em";var T=E.createElement("input");T.type="button";T.onclick=function(){return N(true)};T.value="Cancel";style=T.style;style.margin="10px";style.display="inline";style.width="7em";if(/mac/.test(l.platform.toLowerCase())){S.appendChild(T);S.appendChild(U)}else{S.appendChild(U);S.appendChild(T)}a.addEvent(E.body,"keydown",L);I.style.top="50%";I.style.left="50%";I.style.display="block";if(v.isIE_5or6){I.style.position="absolute";I.style.top=E.documentElement.scrollTop+200+"px";I.style.left="50%"}E.body.appendChild(I);I.style.marginTop=-(C.getHeight(I)/2)+"px";I.style.marginLeft=-(C.getWidth(I)/2)+"px"};G();top.setTimeout(function(){O();var R=P.length;if(K.selectionStart!==undefined){K.selectionStart=0;K.selectionEnd=R}else{if(K.createTextRange){var Q=K.createTextRange();Q.collapse(false);Q.moveStart("character",-R);Q.moveEnd("character",R);Q.select()}}K.focus()},0)};C.getTop=function(H,G){var F=H.offsetTop;if(!G){while(H=H.offsetParent){F+=H.offsetTop}}return F};C.getHeight=function(F){return F.offsetHeight||F.scrollHeight};C.getWidth=function(F){return F.offsetWidth||F.scrollWidth};C.getPageSize=function(){var G,H;var F,K;if(self.innerHeight&&self.scrollMaxY){G=E.body.scrollWidth;H=self.innerHeight+self.scrollMaxY}else{if(E.body.scrollHeight>E.body.offsetHeight){G=E.body.scrollWidth;H=E.body.scrollHeight}else{G=E.body.offsetWidth;H=E.body.offsetHeight}}if(self.innerHeight){F=self.innerWidth;K=self.innerHeight}else{if(E.documentElement&&E.documentElement.clientHeight){F=E.documentElement.clientWidth;K=E.documentElement.clientHeight}else{if(E.body){F=E.body.clientWidth;K=E.body.clientHeight}}}var J=Math.max(G,F);var I=Math.max(H,K);return[J,I,F,K]};y.inputPoller=function(O,H){var F=this;var K=y.panels.input;var G;var I;var L;var J;this.tick=function(){if(!a.isVisible(K)){return}if(K.selectionStart||K.selectionStart===0){var Q=K.selectionStart;var P=K.selectionEnd;if(Q!=G||P!=I){G=Q;I=P;if(L!=K.value){L=K.value;return true}}}return false};var N=function(){if(!a.isVisible(K)){return}if(F.tick()){O()}};var M=function(){J=top.setInterval(N,H)};this.destroy=function(){top.clearInterval(J)};M()};y.undoManager=function(Q){var U=this;var O=[];var M=0;var L="none";var G;var R;var H;var K;var F=function(W,V){if(L!=W){L=W;if(!V){I()}}if(!v.isIE||L!="moving"){H=top.setTimeout(N,1)}else{K=null}};var N=function(){K=new y.TextareaState();R.tick();H=undefined};this.setCommandMode=function(){L="command";I();H=top.setTimeout(N,0)};this.canUndo=function(){return M>1};this.canRedo=function(){if(O[M+1]){return true}return false};this.undo=function(){if(U.canUndo()){if(G){G.restore();G=null}else{O[M]=new y.TextareaState();O[--M].restore();if(Q){Q()}}}L="none";y.panels.input.focus();N()};this.redo=function(){if(U.canRedo()){O[++M].restore();if(Q){Q()}}L="none";y.panels.input.focus();N()};var I=function(){var V=K||new y.TextareaState();if(!V){return false}if(L=="moving"){if(!G){G=V}return}if(G){if(O[M-1].text!=G.text){O[M++]=G}G=null}O[M++]=V;O[M+1]=null;if(Q){Q()}};var P=function(V){var X=false;if(V.ctrlKey||V.metaKey){var W=V.charCode||V.keyCode;var Y=String.fromCharCode(W);switch(Y){case"y":U.redo();X=true;break;case"z":if(!V.shiftKey){U.undo()}else{U.redo()}X=true;break}}if(X){if(V.preventDefault){V.preventDefault()}if(top.event){top.event.returnValue=false}return}};var T=function(V){if(!V.ctrlKey&&!V.metaKey){var W=V.keyCode;if((W>=33&&W<=40)||(W>=63232&&W<=63235)){F("moving")}else{if(W==8||W==46||W==127){F("deleting")}else{if(W==13){F("newlines")}else{if(W==27){F("escape")}else{if((W<16||W>20)&&W!=91){F("typing")}}}}}}};var J=function(){a.addEvent(y.panels.input,"keypress",function(W){if((W.ctrlKey||W.metaKey)&&(W.keyCode==89||W.keyCode==90)){W.preventDefault()}});var V=function(){if(v.isIE||(K&&K.text!=y.panels.input.value)){if(H==undefined){L="paste";I();N()}}};R=new y.inputPoller(V,x);a.addEvent(y.panels.input,"keydown",P);a.addEvent(y.panels.input,"keydown",T);a.addEvent(y.panels.input,"mousedown",function(){F("moving")});y.panels.input.onpaste=V;y.panels.input.ondrop=V};var S=function(){J();N();I()};this.destroy=function(){if(R){R.destroy()}};S()};y.editor=function(O){if(!O){O=function(){}}var L=y.panels.input;var I=0;var P=this;var K;var R;var G;var M;var N;var U=function(W){L.focus();if(W.textOp){if(N){N.setCommandMode()}var Y=new y.TextareaState();if(!Y){return}var Z=Y.getChunks();var V=function(){L.focus();if(Z){Y.setChunks(Z)}Y.restore();O()};var X=W.textOp(Z,V);if(!X){V()}}if(W.execute){W.execute(P)}};var S=function(){if(N){F(document.getElementById("wmd-undo-button"),N.canUndo());F(document.getElementById("wmd-redo-button"),N.canRedo())}};var F=function(V,X){var Y="0px";var Z="-20px";var W="-40px";if(X){V.style.backgroundPosition=V.XShift+" "+Y;V.onmouseover=function(){this.style.backgroundPosition=this.XShift+" "+W};V.onmouseout=function(){this.style.backgroundPosition=this.XShift+" "+Y};if(v.isIE){V.onmousedown=function(){y.ieRetardedClick=true;y.ieCachedRange=document.selection.createRange()}}if(!V.isHelp){V.onclick=function(){if(this.onmouseout){this.onmouseout()}U(this);return false}}}else{V.style.backgroundPosition=V.XShift+" "+Z;V.onmouseover=V.onmouseout=V.onclick=function(){}}};var J=function(){var Z=document.getElementById("wmd-button-bar");var W="0px";var Y="-20px";var ae="-40px";var ak=document.createElement("ul");ak.id="wmd-button-row";ak=Z.appendChild(ak);var ad=document.createElement("li");ad.className="wmd-button";ad.id="wmd-bold-button";ad.title=c;ad.XShift="0px";ad.textOp=h.doBold;F(ad,true);ak.appendChild(ad);var ac=document.createElement("li");ac.className="wmd-button";ac.id="wmd-italic-button";ac.title=f;ac.XShift="-20px";ac.textOp=h.doItalic;F(ac,true);ak.appendChild(ac);var ah=document.createElement("li");ah.className="wmd-spacer";ah.id="wmd-spacer1";ak.appendChild(ah);var ai=document.createElement("li");ai.className="wmd-button";ai.id="wmd-link-button";ai.title=z;ai.XShift="-40px";ai.textOp=function(ap,aq){return h.doLinkOrImage(ap,aq,false)};F(ai,true);ak.appendChild(ai);var al=document.createElement("li");al.className="wmd-button";al.id="wmd-quote-button";al.title=u;al.XShift="-60px";al.textOp=h.doBlockquote;F(al,true);ak.appendChild(al);var am=document.createElement("li");am.className="wmd-button";am.id="wmd-code-button";am.title=e;am.XShift="-80px";am.textOp=h.doCode;F(am,true);ak.appendChild(am);var aa=document.createElement("li");aa.className="wmd-button";aa.id="wmd-image-button";aa.title=d;aa.XShift="-100px";aa.textOp=function(ap,aq){return h.doLinkOrImage(ap,aq,true)};F(aa,true);ak.appendChild(aa);var ag=document.createElement("li");ag.className="wmd-spacer";ag.id="wmd-spacer2";ak.appendChild(ag);var ab=document.createElement("li");ab.className="wmd-button";ab.id="wmd-olist-button";ab.title=q;ab.XShift="-120px";ab.textOp=function(ap,aq){h.doList(ap,aq,true)};F(ab,true);ak.appendChild(ab);var ao=document.createElement("li");ao.className="wmd-button";ao.id="wmd-ulist-button";ao.title=t;ao.XShift="-140px";ao.textOp=function(ap,aq){h.doList(ap,aq,false)};F(ao,true);ak.appendChild(ao);var aj=document.createElement("li");aj.className="wmd-button";aj.id="wmd-heading-button";aj.title=i;aj.XShift="-160px";aj.textOp=h.doHeading;F(aj,true);ak.appendChild(aj);var X=document.createElement("li");X.className="wmd-button";X.id="wmd-hr-button";X.title=p;X.XShift="-180px";X.textOp=h.doHorizontalRule;F(X,true);ak.appendChild(X);var af=document.createElement("li");af.className="wmd-spacer";af.id="wmd-spacer3";ak.appendChild(af);var V=document.createElement("li");V.className="wmd-button";V.id="wmd-undo-button";V.title=m;V.XShift="-200px";V.execute=function(ap){ap.undo()};F(V,true);ak.appendChild(V);var an=document.createElement("li");an.className="wmd-button";an.id="wmd-redo-button";an.title=j;if(/win/.test(l.platform.toLowerCase())){an.title=j}else{an.title="重做 - Ctrl+Shift+Z"}an.XShift="-220px";an.execute=function(ap){ap.redo()};F(an,true);ak.appendChild(an);S()};var H=function(){if(/\?noundo/.test(E.location.href)){y.nativeUndo=true}if(!y.nativeUndo){N=new y.undoManager(function(){O();S()})}J();var W="keydown";if(v.isOpera){W="keypress"}a.addEvent(L,W,function(Y){if(Y.ctrlKey||Y.metaKey){var Z=Y.charCode||Y.keyCode;var X=String.fromCharCode(Z).toLowerCase();if(Z===46){X=""}if(Z===190){X="."}switch(X){case"b":U(document.getElementById("wmd-bold-button"));break;case"i":U(document.getElementById("wmd-italic-button"));break;case"l":U(document.getElementById("wmd-link-button"));break;case".":U(document.getElementById("wmd-quote-button"));break;case"k":U(document.getElementById("wmd-code-button"));break;case"g":U(document.getElementById("wmd-image-button"));break;case"o":U(document.getElementById("wmd-olist-button"));break;case"u":U(document.getElementById("wmd-ulist-button"));break;case"h":U(document.getElementById("wmd-heading-button"));break;case"r":U(document.getElementById("wmd-hr-button"));break;case"y":U(document.getElementById("wmd-redo-button"));break;case"z":if(Y.shiftKey){U(document.getElementById("wmd-redo-button"))}else{U(document.getElementById("wmd-undo-button"))}break;default:return}if(Y.preventDefault){Y.preventDefault()}if(top.event){top.event.returnValue=false}}});a.addEvent(L,"keyup",function(X){if(X.shiftKey&&!X.ctrlKey&&!X.metaKey){var Y=X.charCode||X.keyCode;if(Y===13){fakeButton={};fakeButton.textOp=h.doAutoindent;U(fakeButton)}}});if(L.form){var V=L.form.onsubmit;L.form.onsubmit=function(){Q();if(V){return V.apply(this,arguments)}}}};var Q=function(){if(y.showdown){var V=new y.showdown.converter()}var W=L.value;var X=function(){L.value=W};if(!/markdown/.test(y.wmd_env.output.toLowerCase())){if(V){L.value=V.makeHtml(W);top.setTimeout(X,0)}}return true};this.undo=function(){if(N){N.undo()}};this.redo=function(){if(N){N.redo()}};var T=function(){H()};this.destroy=function(){if(N){N.destroy()}if(G.parentNode){G.parentNode.removeChild(G)}if(L){L.style.marginTop=""}top.clearInterval(M)};T()};y.TextareaState=function(){var F=this;var G=y.panels.input;this.init=function(){if(!a.isVisible(G)){return}this.setInputAreaSelectionStartEnd();this.scrollTop=G.scrollTop;if(!this.text&&G.selectionStart||G.selectionStart===0){this.text=G.value}};this.setInputAreaSelection=function(){if(!a.isVisible(G)){return}if(G.selectionStart!==undefined&&!v.isOpera){G.focus();G.selectionStart=F.start;G.selectionEnd=F.end;G.scrollTop=F.scrollTop}else{if(E.selection){if(E.activeElement&&E.activeElement!==G){return}G.focus();var H=G.createTextRange();H.moveStart("character",-G.value.length);H.moveEnd("character",-G.value.length);H.moveEnd("character",F.end);H.moveStart("character",F.start);H.select()}}};this.setInputAreaSelectionStartEnd=function(){if(G.selectionStart||G.selectionStart===0){F.start=G.selectionStart;F.end=G.selectionEnd}else{if(E.selection){F.text=a.fixEolChars(G.value);var K;if(y.ieRetardedClick&&y.ieCachedRange){K=y.ieCachedRange;y.ieRetardedClick=false}else{K=E.selection.createRange()}var L=a.fixEolChars(K.text);var J="\x07";var I=J+L+J;K.text=I;var M=a.fixEolChars(G.value);K.moveStart("character",-I.length);K.text=L;F.start=M.indexOf(J);F.end=M.lastIndexOf(J)-J.length;var H=F.text.length-a.fixEolChars(G.value).length;if(H){K.moveStart("character",-L.length);while(H--){L+="\n";F.end+=1}K.text=L}this.setInputAreaSelection()}}};this.restore=function(){if(F.text!=undefined&&F.text!=G.value){G.value=F.text}this.setInputAreaSelection();G.scrollTop=F.scrollTop};this.getChunks=function(){var H=new y.Chunks();H.before=a.fixEolChars(F.text.substring(0,F.start));H.startTag="";H.selection=a.fixEolChars(F.text.substring(F.start,F.end));H.endTag="";H.after=a.fixEolChars(F.text.substring(F.end));H.scrollTop=F.scrollTop;return H};this.setChunks=function(H){H.before=H.before+H.startTag;H.after=H.endTag+H.after;if(v.isOpera){H.before=H.before.replace(/\n/g,"\r\n");H.selection=H.selection.replace(/\n/g,"\r\n");H.after=H.after.replace(/\n/g,"\r\n")}this.start=H.before.length;this.end=H.before.length+H.selection.length;this.text=H.before+H.selection+H.after;this.scrollTop=H.scrollTop};this.init()};y.Chunks=function(){};y.Chunks.prototype.findTags=function(G,I){var F=this;var H;if(G){H=a.extendRegExp(G,"","$");this.before=this.before.replace(H,function(J){F.startTag=F.startTag+J;return""});H=a.extendRegExp(G,"^","");this.selection=this.selection.replace(H,function(J){F.startTag=F.startTag+J;return""})}if(I){H=a.extendRegExp(I,"","$");this.selection=this.selection.replace(H,function(J){F.endTag=J+F.endTag;return""});H=a.extendRegExp(I,"^","");this.after=this.after.replace(H,function(J){F.endTag=J+F.endTag;return""})}};y.Chunks.prototype.trimWhitespace=function(F){this.selection=this.selection.replace(/^(\s*)/,"");if(!F){this.before+=s.$1}this.selection=this.selection.replace(/(\s*)$/,"");if(!F){this.after=s.$1+this.after}};y.Chunks.prototype.skipLines=function(H,G,F){if(H===undefined){H=1}if(G===undefined){G=1}H++;G++;var I;var J;this.selection=this.selection.replace(/(^\n*)/,"");this.startTag=this.startTag+s.$1;this.selection=this.selection.replace(/(\n*$)/,"");this.endTag=this.endTag+s.$1;this.startTag=this.startTag.replace(/(^\n*)/,"");this.before=this.before+s.$1;this.endTag=this.endTag.replace(/(\n*$)/,"");this.after=this.after+s.$1;if(this.before){I=J="";while(H--){I+="\\n?";J+="\n"}if(F){I="\\n*"}this.before=this.before.replace(new s(I+"$",""),J)}if(this.after){I=J="";while(G--){I+="\\n?";J+="\n"}if(F){I="\\n*"}this.after=this.after.replace(new s(I,""),J)}};h.prefixes="(?:\\s{4,}|\\s*>|\\s*-\\s+|\\s*\\d+\\.|=|\\+|-|_|\\*|#|\\s*\\[[^\n]]+\\]:)";h.unwrap=function(G){var F=new s("([^\\n])\\n(?!(\\n|"+h.prefixes+"))","g");G.selection=G.selection.replace(F,"$1 $2")};h.wrap=function(G,F){h.unwrap(G);var H=new s("(.{1,"+F+"})( +|$\\n?)","gm");G.selection=G.selection.replace(H,function(I,J){if(new s("^"+h.prefixes,"").test(I)){return I}return J+"\n"});G.selection=G.selection.replace(/\s+$/,"")};h.doBold=function(F,G){return h.doBorI(F,G,2,"strong text")};h.doItalic=function(F,G){return h.doBorI(F,G,1,"emphasized text")};h.doBorI=function(L,J,K,F){L.trimWhitespace();L.selection=L.selection.replace(/\n{2,}/g,"\n");L.before.search(/(\**$)/);var I=s.$1;L.after.search(/(^\**)/);var G=s.$1;var M=Math.min(I.length,G.length);if((M>=K)&&(M!=2||K!=1)){L.before=L.before.replace(s("[*]{"+K+"}$",""),"");L.after=L.after.replace(s("^[*]{"+K+"}",""),"")}else{if(!L.selection&&G){L.after=L.after.replace(/^([*_]*)/,"");L.before=L.before.replace(/(\s?)$/,"");var H=s.$1;L.before=L.before+G+H}else{if(!L.selection&&!G){L.selection=F}var N=K<=1?"*":"**";L.before=L.before+N;L.after=N+L.after}}return};h.stripLinkDefs=function(G,F){G=G.replace(/^[ ]{0,3}\[(\d+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|$)/gm,function(K,L,H,I,J){F[L]=K.replace(/\s*$/,"");if(I){F[L]=K.replace(/["(](.+?)[")]$/,"");return I+J}return""});return G};h.addLinkDef=function(M,I){var F=0;var H={};M.before=h.stripLinkDefs(M.before,H);M.selection=h.stripLinkDefs(M.selection,H);M.after=h.stripLinkDefs(M.after,H);var G="";var L=/(\[(?:\[[^\]]*\]|[^\[\]])*\][ ]?(?:\n[ ]*)?\[)(\d+)(\])/g;var K=function(O){F++;O=O.replace(/^[ ]{0,3}\[(\d+)\]:/,"  ["+F+"]:");G+="\n"+O};var J=function(P,Q,R,O){if(H[R]){K(H[R]);return Q+F+O}return P};M.before=M.before.replace(L,J);if(I){K(I)}else{M.selection=M.selection.replace(L,J)}var N=F;M.after=M.after.replace(L,J);if(M.after){M.after=M.after.replace(/\n*$/,"")}if(!M.after){M.selection=M.selection.replace(/\n*$/,"")}M.after+="\n\n"+G;return N};h.doLinkOrImage=function(F,G,I){F.trimWhitespace();F.findTags(/\s*!?\[/,/\][ ]?(?:\n[ ]*)?(\[.*?\])?/);if(F.endTag.length>1){F.startTag=F.startTag.replace(/!?\[/,"");F.endTag="";h.addLinkDef(F,null)}else{if(/\n\n/.test(F.selection)){h.addLinkDef(F,null);return}var H=function(L){if(L!==null){F.startTag=F.endTag="";var K=" [999]: "+L;var J=h.addLinkDef(F,K);F.startTag=I?"![":"[";F.endTag="]["+J+"]";if(!F.selection){if(I){F.selection="alt text"}else{F.selection="link text"}}}G()};if(I){a.prompt(B,b,H,1)}else{a.prompt(D,g,H)}return true}};a.makeAPI=function(){y.wmd={};y.wmd.editor=y.editor;y.wmd.previewManager=y.previewManager};a.startEditor=function(){if(y.wmd_env.autostart===false){a.makeAPI();return}var G;var F;var H=function(){y.panels=new y.PanelCollection();F=new y.previewManager();var I=F.refresh;G=new y.editor(I);F.refresh(true)};a.addEvent(top,"load",H)};y.previewManager=function(){var H=this;var V;var F;var N;var M;var S;var O;var I=3000;var P="delayed";var K=function(X,Y){a.addEvent(X,"input",Y);X.onpaste=Y;X.ondrop=Y;a.addEvent(X,"keypress",Y);a.addEvent(X,"keydown",Y);F=new y.inputPoller(Y,A)};var R=function(){var X=0;if(top.innerHeight){X=top.pageYOffset}else{if(E.documentElement&&E.documentElement.scrollTop){X=E.documentElement.scrollTop}else{if(E.body){X=E.body.scrollTop}}}return X};var L=function(){if(!y.panels.preview&&!y.panels.output){return}var Z=y.panels.input.value;if(Z&&Z==S){return}else{S=Z}var Y=new Date().getTime();if(!V&&y.showdown){V=new y.showdown.converter()}if(V){Z=V.makeHtml(Z)}var X=new Date().getTime();M=X-Y;G(Z);O=Z};var U=function(){if(N){top.clearTimeout(N);N=undefined}if(P!=="manual"){var X=0;if(P==="delayed"){X=M}if(X>I){X=I}N=top.setTimeout(L,X)}};var J=function(X){if(X.scrollHeight<=X.clientHeight){return 1}return X.scrollTop/(X.scrollHeight-X.clientHeight)};var W=function(){if(y.panels.preview){y.panels.preview.scrollTop=(y.panels.preview.scrollHeight-y.panels.preview.clientHeight)*J(y.panels.preview)}if(y.panels.output){y.panels.output.scrollTop=(y.panels.output.scrollHeight-y.panels.output.clientHeight)*J(y.panels.output)}};this.refresh=function(X){if(X){S="";L()}else{U()}};this.processingTime=function(){return M};this.output=function(){return O};this.setUpdateMode=function(X){P=X;H.refresh()};var Q=true;var G=function(aa){var X=C.getTop(y.panels.input)-R();if(y.panels.output){if(y.panels.output.value!==undefined){y.panels.output.value=aa;y.panels.output.readOnly=true}else{var Z=aa.replace(/&/g,"&amp;");Z=Z.replace(/</g,"&lt;");y.panels.output.innerHTML="<pre><code>"+Z+"</code></pre>"}}if(y.panels.preview){y.panels.preview.innerHTML=aa}W();if(Q){Q=false;return}var Y=C.getTop(y.panels.input)-R();if(v.isIE){top.setTimeout(function(){top.scrollBy(0,Y-X)},0)}else{top.scrollBy(0,Y-X)}};var T=function(){K(y.panels.input,U);L();if(y.panels.preview){y.panels.preview.scrollTop=0}if(y.panels.output){y.panels.output.scrollTop=0}};this.destroy=function(){if(F){F.destroy()}};T()};h.doAutoindent=function(F,G){F.before=F.before.replace(/(\n|^)[ ]{0,3}([*+-]|\d+[.])[ \t]*\n$/,"\n\n");F.before=F.before.replace(/(\n|^)[ ]{0,3}>[ \t]*\n$/,"\n\n");F.before=F.before.replace(/(\n|^)[ \t]+\n$/,"\n\n");if(/(\n|^)[ ]{0,3}([*+-]|\d+[.])[ \t]+.*\n$/.test(F.before)){if(h.doList){h.doList(F)}}if(/(\n|^)[ ]{0,3}>[ \t]+.*\n$/.test(F.before)){if(h.doBlockquote){h.doBlockquote(F)}}if(/(\n|^)(\t|[ ]{4,}).*\n$/.test(F.before)){if(h.doCode){h.doCode(F)}}};h.doBlockquote=function(F,G){F.selection=F.selection.replace(/^(\n*)([^\r]+?)(\n*)$/,function(L,K,J,I){F.before+=K;F.after=I+F.after;return J});F.before=F.before.replace(/(>[ \t]*)$/,function(J,I){F.selection=I+F.selection;return""});F.selection=F.selection.replace(/^(\s|>)+$/,"");F.selection=F.selection||"Blockquote";if(F.before){F.before=F.before.replace(/\n?$/,"\n")}if(F.after){F.after=F.after.replace(/^\n?/,"\n")}F.before=F.before.replace(/(((\n|^)(\n[ \t]*)*>(.+\n)*.*)+(\n[ \t]*)*$)/,function(I){F.startTag=I;return""});F.after=F.after.replace(/^(((\n|^)(\n[ \t]*)*>(.+\n)*.*)+(\n[ \t]*)*)/,function(I){F.endTag=I;return""});var H=function(J){var I=J?"> ":"";if(F.startTag){F.startTag=F.startTag.replace(/\n((>|\s)*)\n$/,function(L,K){return"\n"+K.replace(/^[ ]{0,3}>?[ \t]*$/gm,I)+"\n"})}if(F.endTag){F.endTag=F.endTag.replace(/^\n((>|\s)*)\n/,function(L,K){return"\n"+K.replace(/^[ ]{0,3}>?[ \t]*$/gm,I)+"\n"})}};if(/^(?![ ]{0,3}>)/m.test(F.selection)){h.wrap(F,y.wmd_env.lineLength-2);F.selection=F.selection.replace(/^/gm,"> ");H(true);F.skipLines()}else{F.selection=F.selection.replace(/^[ ]{0,3}> ?/gm,"");h.unwrap(F);H(false);if(!/^(\n|^)[ ]{0,3}>/.test(F.selection)&&F.startTag){F.startTag=F.startTag.replace(/\n{0,2}$/,"\n\n")}if(!/(\n|^)[ ]{0,3}>.*$/.test(F.selection)&&F.endTag){F.endTag=F.endTag.replace(/^\n{0,2}/,"\n\n")}}if(!/\n/.test(F.selection)){F.selection=F.selection.replace(/^(> *)/,function(I,J){F.startTag+=J;return""})}};h.doCode=function(F,G){var I=/\S[ ]*$/.test(F.before);var K=/^[ ]*\S/.test(F.after);if((!K&&!I)||/\n/.test(F.selection)){F.before=F.before.replace(/[ ]{4}$/,function(L){F.selection=L+F.selection;return""});var J=1;var H=1;if(/\n(\t|[ ]{4,}).*\n$/.test(F.before)){J=0}if(/^\n(\t|[ ]{4,})/.test(F.after)){H=0}F.skipLines(J,H);if(!F.selection){F.startTag="    ";F.selection="enter code here"}else{if(/^[ ]{0,3}\S/m.test(F.selection)){F.selection=F.selection.replace(/^/gm,"    ")}else{F.selection=F.selection.replace(/^[ ]{4}/gm,"")}}}else{F.trimWhitespace();F.findTags(/`/,/`/);if(!F.startTag&&!F.endTag){F.startTag=F.endTag="`";if(!F.selection){F.selection="enter code here"}}else{if(F.endTag&&!F.startTag){F.before+=F.endTag;F.endTag=""}else{F.startTag=F.endTag=""}}}};h.doList=function(Q,J,I){var S=/(\n|^)(([ ]{0,3}([*+-]|\d+[.])[ \t]+.*)(\n.+|\n{2,}([*+-].*|\d+[.])[ \t]+.*|\n{2,}[ \t]+\S.*)*)\n*$/;var R=/^\n*(([ ]{0,3}([*+-]|\d+[.])[ \t]+.*)(\n.+|\n{2,}([*+-].*|\d+[.])[ \t]+.*|\n{2,}[ \t]+\S.*)*)\n*/;var F="-";var N=1;var L=function(){var T;if(I){T=" "+N+". ";N++}else{T=" "+F+" "}return T};var M=function(T){if(I===undefined){I=/^\s*\d/.test(T)}T=T.replace(/^[ ]{0,3}([*+-]|\d+[.])\s/gm,function(U){return L()});return T};Q.findTags(/(\n|^)*[ ]{0,3}([*+-]|\d+[.])\s+/,null);if(Q.before&&!/\n$/.test(Q.before)&&!/^\n/.test(Q.startTag)){Q.before+=Q.startTag;Q.startTag=""}if(Q.startTag){var H=/\d+[.]/.test(Q.startTag);Q.startTag="";Q.selection=Q.selection.replace(/\n[ ]{4}/g,"\n");h.unwrap(Q);Q.skipLines();if(H){Q.after=Q.after.replace(R,M)}if(I==H){return}}var K=1;Q.before=Q.before.replace(S,function(T){if(/^\s*([*+-])/.test(T)){F=s.$1}K=/[^\n]\n\n[^\n]/.test(T)?1:0;return M(T)});if(!Q.selection){Q.selection="List item"}var O=L();var G=1;Q.after=Q.after.replace(R,function(T){G=/[^\n]\n\n[^\n]/.test(T)?1:0;return M(T)});Q.trimWhitespace(true);Q.skipLines(K,G,true);Q.startTag=O;var P=O.replace(/./g," ");h.wrap(Q,y.wmd_env.lineLength-P.length);Q.selection=Q.selection.replace(/\n/g,"\n"+P)};h.doHeading=function(H,I){H.selection=H.selection.replace(/\s+/g," ");H.selection=H.selection.replace(/(^\s+|\s+$)/g,"");if(!H.selection){H.startTag="## ";H.selection="Heading";H.endTag=" ##";return}var J=0;H.findTags(/#+[ ]*/,/[ ]*#+/);if(/#+/.test(H.startTag)){J=s.lastMatch.length}H.startTag=H.endTag="";H.findTags(null,/\s?(-+|=+)/);if(/=+/.test(H.endTag)){J=1}if(/-+/.test(H.endTag)){J=2}H.startTag=H.endTag="";H.skipLines(1,1);var K=J==0?2:J-1;if(K>0){var G=K>=2?"-":"=";var F=H.selection.length;if(F>y.wmd_env.lineLength){F=y.wmd_env.lineLength}H.endTag="\n";while(F--){H.endTag+=G}}};h.doHorizontalRule=function(F,G){F.startTag="----------\n";F.selection="";F.skipLines(2,1,true)}};Attacklab.wmd_env={};Attacklab.account_options={};Attacklab.wmd_defaults={version:1,output:"Markdown",lineLength:40,delayLoad:false};if(!Attacklab.wmd){Attacklab.wmd=function(){Attacklab.loadEnv=function(){var b=function(d){if(!d){return}for(var c in d){Attacklab.wmd_env[c]=d[c]}};b(Attacklab.wmd_defaults);b(Attacklab.account_options);b(top.wmd_options);Attacklab.full=true;var a="bold italic link blockquote code image ol ul heading hr";Attacklab.wmd_env.buttons=Attacklab.wmd_env.buttons||a};Attacklab.loadEnv()};Attacklab.wmd();Attacklab.wmdBase();Attacklab.Util.startEditor()};
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/wmd-test.html b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/wmd-test.html
new file mode 100644 (file)
index 0000000..d748501
--- /dev/null
@@ -0,0 +1,158 @@
+<!DOCTYPE html>
+<html>
+
+       <head>
+               <title>Test WMD Page</title>
+               
+               <link rel="stylesheet" type="text/css" href="wmd.css" />
+               
+               <meta http-equiv="pragma" content="no-cache">
+               <meta http-equiv="cache-control" content="no-cache">
+               <meta http-equiv="pragma-directive" content="no-cache">
+               <meta http-equiv="cache-directive" content="no-cache">
+               <meta http-equiv="expires" content="0">
+               
+               <script type="text/javascript" src="jQuery/jquery-1.2.6.js"></script>
+               <script type="text/javascript" src="showdown.js"></script>
+       </head>
+       
+       <body>
+               <div id="wmd-button-bar" class="wmd-panel"></div>
+               <br/>
+               <textarea id="editor" class="wmd-panel"></textarea>
+               <br/>
+               <div id="previewer" class="wmd-panel"></div>
+               <br/>
+               <div id="wmd-output" class="wmd-panel"></div>   
+               
+               <p>To test that page up/down and arrow keys work, copy this above the WMD
+               control.</p>
+               
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+               Scroll Down!<br/>
+
+               <script type="text/javascript" src="wmd.js"></script>
+       </body>
+</html>
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/wmd.css b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/wmd.css
new file mode 100644 (file)
index 0000000..c71ba6e
--- /dev/null
@@ -0,0 +1,138 @@
+body 
+{ 
+       background-color: White
+}
+
+.wmd-panel
+{
+       width: 50%;
+       min-width: 500px;
+}
+
+#wmd-editor
+{
+       background-color: Aquamarine;
+}
+
+#wmd-button-bar 
+{
+       width: 100%;
+       background-color: #ffffff;
+}
+
+#wmd-input 
+{ 
+       height: 500px;
+       width: 100%;
+       background-color: Gainsboro;
+       border: 1px solid DarkGray;
+}
+
+#wmd-preview 
+{ 
+       background-color: LightSkyBlue; 
+}
+
+#wmd-output 
+{ 
+       background-color: Pink;
+}
+
+#wmd-button-row 
+{
+       position: relative; 
+       margin-left: 5px;
+       margin-right: 5px;
+       margin-bottom: 5px;
+       margin-top: 10px;
+       padding: 0px;  
+       height: 20px;
+    background-color:#ffffff;
+}
+
+.wmd-spacer
+{
+       width: 1px; 
+       height: 20px; 
+       margin-left: 14px;
+       
+       position: absolute;
+    background-color:#aaaaaa;
+       display: inline-block;
+       list-style: none;
+}
+
+.wmd-button
+{
+       width: 20px; 
+       height: 20px; 
+       margin-left: 5px;
+       margin-right: 5px;
+    background-color:#ffffff;
+       position: absolute;
+       background-image: url(images/wmd-buttons.png);
+       background-repeat: no-repeat;
+       background-position: 0px 0px;
+       display: inline-block; 
+       list-style: none;
+}
+
+.wmd-button > a
+{
+       width: 20px; 
+       height: 20px; 
+       margin-left: 5px;
+       margin-right: 5px;
+
+       position: absolute;
+       display: inline-block; 
+}
+
+
+/* sprite button slicing style information */
+#wmd-button-bar #wmd-bold-button    {left: 0px;   background-position: 0px 0;}
+#wmd-button-bar #wmd-italic-button  {left: 25px;  background-position: -20px 0;}
+#wmd-button-bar #wmd-spacer1        {left: 50px;}
+#wmd-button-bar #wmd-link-button    {left: 75px;  background-position: -40px 0;}
+#wmd-button-bar #wmd-quote-button   {left: 100px;  background-position: -60px 0;}
+#wmd-button-bar #wmd-code-button    {left: 125px;  background-position: -80px 0;}
+#wmd-button-bar #wmd-image-button   {left: 150px;  background-position: -100px 0;}
+#wmd-button-bar #wmd-spacer2        {left: 175px;}
+#wmd-button-bar #wmd-olist-button   {left: 200px;  background-position: -120px 0;}
+#wmd-button-bar #wmd-ulist-button   {left: 225px; background-position: -140px 0;}
+#wmd-button-bar #wmd-heading-button {left: 250px; background-position: -160px 0;}
+#wmd-button-bar #wmd-hr-button      {left: 275px; background-position: -180px 0;}
+#wmd-button-bar #wmd-spacer3        {left: 300px;}
+#wmd-button-bar #wmd-undo-button    {left: 325px; background-position: -200px 0;}
+#wmd-button-bar #wmd-redo-button    {left: 350px; background-position: -220px 0;}
+#wmd-button-bar #wmd-help-button    {right: 0px; background-position: -240px 0;}
+
+
+.wmd-prompt-background
+{
+       background-color: Black;
+}
+
+.wmd-prompt-dialog
+{
+       border: 1px solid #999999;
+       background-color: #F5F5F5;
+}
+
+.wmd-prompt-dialog > div {
+       font-size: 0.8em;
+       font-family: arial, helvetica, sans-serif;
+}
+
+
+.wmd-prompt-dialog > form > input[type="text"] {
+       border: 1px solid #999999;
+       color: black;
+}
+
+.wmd-prompt-dialog > form > input[type="button"]{
+       border: 1px solid #888888;
+       font-family: trebuchet MS, helvetica, sans-serif;
+       font-size: 0.8em;
+       font-weight: bold;
+}
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/wmd.js b/forum/modules/template_loader.py/forum/skins/default/media/js/wmd/wmd.js
new file mode 100644 (file)
index 0000000..f541581
--- /dev/null
@@ -0,0 +1,2448 @@
+jQuery.extend({createUploadIframe:function(d,b){var a="jUploadFrame"+d;if(window.ActiveXObject){var c=document.createElement('<iframe id="'+a+'" name="'+a+'" />');if(typeof b=="boolean"){c.src="javascript:false"}else{if(typeof b=="string"){c.src=b}}}else{var c=document.createElement("iframe");c.id=a;c.name=a}c.style.position="absolute";c.style.top="-1000px";c.style.left="-1000px";document.body.appendChild(c);return c},createUploadForm:function(g,b){var e="jUploadForm"+g;var a="jUploadFile"+g;var d=$('<form  action="" method="POST" name="'+e+'" id="'+e+'" enctype="multipart/form-data"></form>');var c=$("#"+b);var f=$(c).clone();$(c).attr("id",a);$(c).before(f);$(c).appendTo(d);$(d).css("position","absolute");$(d).css("top","-1200px");$(d).css("left","-1200px");$(d).appendTo("body");return d},ajaxFileUpload:function(k){k=jQuery.extend({},jQuery.ajaxSettings,k);var a=new Date().getTime();var b=jQuery.createUploadForm(a,k.fileElementId);var i=jQuery.createUploadIframe(a,k.secureuri);var h="jUploadFrame"+a;var j="jUploadForm"+a;if(k.global&&!jQuery.active++){jQuery.event.trigger("ajaxStart")}var c=false;var f={};if(k.global){jQuery.event.trigger("ajaxSend",[f,k])}var d=function(l){var p=document.getElementById(h);try{if(p.contentWindow){f.responseText=p.contentWindow.document.body?p.contentWindow.document.body.innerText:null;f.responseXML=p.contentWindow.document.XMLDocument?p.contentWindow.document.XMLDocument:p.contentWindow.document}else{if(p.contentDocument){f.responseText=p.contentDocument.document.body?p.contentDocument.document.body.textContent||document.body.innerText:null;f.responseXML=p.contentDocument.document.XMLDocument?p.contentDocument.document.XMLDocument:p.contentDocument.document}}}catch(o){jQuery.handleError(k,f,null,o)}if(f||l=="timeout"){c=true;var m;try{m=l!="timeout"?"success":"error";if(m!="error"){var n=jQuery.uploadHttpData(f,k.dataType);if(k.success){k.success(n,m)}if(k.global){jQuery.event.trigger("ajaxSuccess",[f,k])}}else{jQuery.handleError(k,f,m)}}catch(o){m="error";jQuery.handleError(k,f,m,o)}if(k.global){jQuery.event.trigger("ajaxComplete",[f,k])}if(k.global&&!--jQuery.active){jQuery.event.trigger("ajaxStop")}if(k.complete){k.complete(f,m)}jQuery(p).unbind();setTimeout(function(){try{$(p).remove();$(b).remove()}catch(q){jQuery.handleError(k,f,null,q)}},100);f=null}};if(k.timeout>0){setTimeout(function(){if(!c){d("timeout")}},k.timeout)}try{var b=$("#"+j);$(b).attr("action",k.url);$(b).attr("method","POST");$(b).attr("target",h);if(b.encoding){b.encoding="multipart/form-data"}else{b.enctype="multipart/form-data"}$(b).submit()}catch(g){jQuery.handleError(k,f,null,g)}if(window.attachEvent){document.getElementById(h).attachEvent("onload",d)}else{document.getElementById(h).addEventListener("load",d,false)}return{abort:function(){}}},uploadHttpData:function(r,type){var data=!type;data=type=="xml"||data?r.responseXML:r.responseText;if(type=="script"){jQuery.globalEval(data)}if(type=="json"){eval("data = "+data)}if(type=="html"){jQuery("<div>").html(data).evalScripts()}return data}});
+/*Upload call*/
+function ajaxFileUpload(imageUrl)
+{
+  $("#loading").ajaxStart(function(){
+      $(this).show();
+  }).ajaxComplete(function(){
+      $(this).hide();
+  });
+
+  $("#upload").ajaxStart(function(){
+          $(this).hide();
+      }).ajaxComplete(function(){
+          $(this).show();
+      });
+
+      $.ajaxFileUpload
+      (
+        {
+            url: scriptUrl+'upload/',
+              secureuri:false,
+              fileElementId:'file-upload',
+              dataType: 'xml',
+              success: function (data, status)
+              {
+                  var fileURL = $(data).find('file_url').text();
+                  var error = $(data).find('error').text();
+                  if(error != ''){
+                    alert(error);
+                  }else{
+                    imageUrl.attr('value', fileURL);
+                  }
+
+              },
+              error: function (data, status, e)
+              {
+                  alert(e);
+              }
+          }
+      );
+
+    return false;
+}
+
+var Attacklab = Attacklab || {};
+
+Attacklab.wmdBase = function(){
+
+       // A few handy aliases for readability.
+       var wmd  = top.Attacklab;
+       var doc  = top.document;
+       var re   = top.RegExp;
+       var nav  = top.navigator;
+       
+       // Some namespaces.
+       wmd.Util = {};
+       wmd.Position = {};
+       wmd.Command = {};
+       wmd.Global = {};
+       
+       var util = wmd.Util;
+       var position = wmd.Position;
+       var command = wmd.Command;
+       var global = wmd.Global;
+       
+       
+       // Used to work around some browser bugs where we can't use feature testing.
+       global.isIE             = /msie/.test(nav.userAgent.toLowerCase());
+       global.isIE_5or6        = /msie 6/.test(nav.userAgent.toLowerCase()) || /msie 5/.test(nav.userAgent.toLowerCase());
+       global.isIE_7plus       = global.isIE && !global.isIE_5or6;
+       global.isOpera          = /opera/.test(nav.userAgent.toLowerCase());
+       global.isKonqueror      = /konqueror/.test(nav.userAgent.toLowerCase());
+       
+       var toolbar_strong_label = $.i18n._('bold') + " <strong> Ctrl-B";
+    var toolbar_emphasis_label = $.i18n._('italic') + " <em> Ctrl-I";
+    var toolbar_hyperlink_label = $.i18n._('link') + " <a> Ctrl-L";
+    var toolbar_blockquote_label = $.i18n._('quote') + " <blockquote> Ctrl-.";
+    var toolbar_code_label = $.i18n._('preformatted text') + " <pre><code> Ctrl-K";
+    var toolbar_image_label = $.i18n._('image') + " <img> Ctrl-G";
+    var toolbar_numbered_label = $.i18n._('numbered list') + " <ol> Ctrl-O";
+    var toolbar_bulleted_label = $.i18n._('bulleted list') + " <ul> Ctrl-U";
+    var toolbar_heading_label = $.i18n._('heading') + " <h1>/<h2> Ctrl-H";
+    var toolbar_horizontal_label = $.i18n._('horizontal bar') + " <hr> Ctrl-R";
+    var toolbar_undo_label = $.i18n._('undo') + " Ctrl-Z";
+    var toolbar_redo_label = $.i18n._('redo') + " Ctrl-Y";
+
+       // -------------------------------------------------------------------
+       //  YOUR CHANGES GO HERE
+       //
+       // I've tried to localize the things you are likely to change to 
+       // this area.
+       // -------------------------------------------------------------------
+       
+       // The text that appears on the upper part of the dialog box when
+       // entering links.
+       var imageDialogText = "<p style='margin-top: 0px'>" + $.i18n._('enter image url') + "</p>";
+       var linkDialogText = "<p style='margin-top: 0px'>" + $.i18n._('enter url') + "</p>";
+    var uploadImageHTML ="<div>" + $.i18n._('upload image') + "</div>" +
+            "<input type=\"file\" name=\"file-upload\" id=\"file-upload\" size=\"26\" "+
+            "onchange=\"return ajaxFileUpload($('#image-url'));\"/><br>" +
+            "<img id=\"loading\" src=\"" + mediaUrl("media/images/indicator.gif") + "\" style=\"display:none;\"/>";
+
+    
+       // The default text that appears in the dialog input box when entering
+       // links.
+       var imageDefaultText = "http://";
+       var linkDefaultText = "http://";
+       
+       // The location of your button images relative to the base directory.
+       var imageDirectory = "images/";
+       
+       // Some intervals in ms.  These can be adjusted to reduce the control's load.
+       var previewPollInterval = 500;
+       var pastePollInterval = 100;
+       
+       // The link and title for the help button
+       var helpLink = "http://wmd-editor.com/";
+       var helpHoverTitle = "WMD website";
+       var helpTarget = "_blank";
+       
+       // -------------------------------------------------------------------
+       //  END OF YOUR CHANGES
+       // -------------------------------------------------------------------
+       
+       // A collection of the important regions on the page.
+       // Cached so we don't have to keep traversing the DOM.
+       wmd.PanelCollection = function(){
+               this.buttonBar = doc.getElementById("wmd-button-bar");
+               this.preview = doc.getElementById("previewer");
+               this.output = doc.getElementById("wmd-output");
+               this.input = doc.getElementById("editor");
+       };
+       
+       // This PanelCollection object can't be filled until after the page
+       // has loaded.
+       wmd.panels = undefined;
+       
+       // Internet explorer has problems with CSS sprite buttons that use HTML
+       // lists.  When you click on the background image "button", IE will 
+       // select the non-existent link text and discard the selection in the
+       // textarea.  The solution to this is to cache the textarea selection
+       // on the button's mousedown event and set a flag.  In the part of the
+       // code where we need to grab the selection, we check for the flag
+       // and, if it's set, use the cached area instead of querying the
+       // textarea.
+       //
+       // This ONLY affects Internet Explorer (tested on versions 6, 7
+       // and 8) and ONLY on button clicks.  Keyboard shortcuts work
+       // normally since the focus never leaves the textarea.
+       wmd.ieCachedRange = null;               // cached textarea selection
+       wmd.ieRetardedClick = false;    // flag
+       
+       // Returns true if the DOM element is visible, false if it's hidden.
+       // Checks if display is anything other than none.
+       util.isVisible = function (elem) {
+       
+           if (window.getComputedStyle) {
+               // Most browsers
+                       return window.getComputedStyle(elem, null).getPropertyValue("display") !== "none";
+               }
+               else if (elem.currentStyle) {
+                   // IE
+                       return elem.currentStyle["display"] !== "none";
+               }
+       };
+       
+       
+       // Adds a listener callback to a DOM element which is fired on a specified
+       // event.
+       util.addEvent = function(elem, event, listener){
+               if (elem.attachEvent) {
+                       // IE only.  The "on" is mandatory.
+                       elem.attachEvent("on" + event, listener);
+               }
+               else {
+                       // Other browsers.
+                       elem.addEventListener(event, listener, false);
+               }
+       };
+
+       
+       // Removes a listener callback from a DOM element which is fired on a specified
+       // event.
+       util.removeEvent = function(elem, event, listener){
+               if (elem.detachEvent) {
+                       // IE only.  The "on" is mandatory.
+                       elem.detachEvent("on" + event, listener);
+               }
+               else {
+                       // Other browsers.
+                       elem.removeEventListener(event, listener, false);
+               }
+       };
+
+       // Converts \r\n and \r to \n.
+       util.fixEolChars = function(text){
+               text = text.replace(/\r\n/g, "\n");
+               text = text.replace(/\r/g, "\n");
+               return text;
+       };
+
+       // Extends a regular expression.  Returns a new RegExp
+       // using pre + regex + post as the expression.
+       // Used in a few functions where we have a base
+       // expression and we want to pre- or append some
+       // conditions to it (e.g. adding "$" to the end).
+       // The flags are unchanged.
+       //
+       // regex is a RegExp, pre and post are strings.
+       util.extendRegExp = function(regex, pre, post){
+               
+               if (pre === null || pre === undefined)
+               {
+                       pre = "";
+               }
+               if(post === null || post === undefined)
+               {
+                       post = "";
+               }
+               
+               var pattern = regex.toString();
+               var flags = "";
+               
+               // Replace the flags with empty space and store them.
+               // Technically, this can match incorrect flags like "gmm".
+               var result = pattern.match(/\/([gim]*)$/);
+               if (result === null) {
+                       flags = result[0];
+               }
+               else {
+                       flags = "";
+               }
+               
+               // Remove the flags and slash delimiters from the regular expression.
+               pattern = pattern.replace(/(^\/|\/[gim]*$)/g, "");
+               pattern = pre + pattern + post;
+               
+               return new RegExp(pattern, flags);
+       }
+
+       
+       // Sets the image for a button passed to the WMD editor.
+       // Returns a new element with the image attached.
+       // Adds several style properties to the image.
+       util.createImage = function(img){
+               
+               var imgPath = imageDirectory + img;
+               
+               var elem = doc.createElement("img");
+               elem.className = "wmd-button";
+               elem.src = imgPath;
+
+               return elem;
+       };
+       
+
+       // This simulates a modal dialog box and asks for the URL when you
+       // click the hyperlink or image buttons.
+       //
+       // text: The html for the input box.
+       // defaultInputText: The default value that appears in the input box.
+       // makeLinkMarkdown: The function which is executed when the prompt is dismissed, either via OK or Cancel
+       util.prompt = function(text, defaultInputText, makeLinkMarkdown){
+       
+               // These variables need to be declared at this level since they are used
+               // in multiple functions.
+               var dialog;                     // The dialog box.
+               var background;         // The background beind the dialog box.
+               var input;                      // The text box where you enter the hyperlink.
+        var type = 0;
+        // The dialog box type(0: Link, 1: Image)
+        if(arguments.length == 4){
+            type = arguments[3];
+        }
+
+               if (defaultInputText === undefined) {
+                       defaultInputText = "";
+               }
+               
+               // Used as a keydown event handler. Esc dismisses the prompt.
+               // Key code 27 is ESC.
+               var checkEscape = function(key){
+                       var code = (key.charCode || key.keyCode);
+                       if (code === 27) {
+                               close(true);
+                       }
+               };
+               
+               // Dismisses the hyperlink input box.
+               // isCancel is true if we don't care about the input text.
+               // isCancel is false if we are going to keep the text.
+               var close = function(isCancel){
+                       util.removeEvent(doc.body, "keydown", checkEscape);
+                       var text = input.value;
+
+                       if (isCancel){
+                               text = null;
+                       }
+                       else{
+                               // Fixes common pasting errors.
+                               text = text.replace('http://http://', 'http://');
+                               text = text.replace('http://https://', 'https://');
+                               text = text.replace('http://ftp://', 'ftp://');
+                               
+                               if (text.indexOf('http://') === -1 && text.indexOf('ftp://') === -1 && text.indexOf('https://') === -1 && text.indexOf('/') !== 0) {
+                                       text = 'http://' + text;
+                               }
+                       }
+                       
+                       dialog.parentNode.removeChild(dialog);
+                       background.parentNode.removeChild(background);
+                       makeLinkMarkdown(text);
+                       return false;
+               };
+               
+               // Creates the background behind the hyperlink text entry box.
+               // Most of this has been moved to CSS but the div creation and
+               // browser-specific hacks remain here.
+               var createBackground = function(){
+               
+                       background = doc.createElement("div");
+                       background.className = "wmd-prompt-background";
+                       style = background.style;
+                       style.position = "absolute";
+                       style.top = "0";
+                       
+                       style.zIndex = "1000";
+                       
+                       // Some versions of Konqueror don't support transparent colors
+                       // so we make the whole window transparent.
+                       //
+                       // Is this necessary on modern konqueror browsers?
+                       if (global.isKonqueror){
+                               style.backgroundColor = "transparent";
+                       }
+                       else if (global.isIE){
+                               style.filter = "alpha(opacity=50)";
+                       }
+                       else {
+                               style.opacity = "0.5";
+                       }
+                       
+                       var pageSize = position.getPageSize();
+                       style.height = pageSize[1] + "px";
+                       
+                       if(global.isIE){
+                               style.left = doc.documentElement.scrollLeft;
+                               style.width = doc.documentElement.clientWidth;
+                       }
+                       else {
+                               style.left = "0";
+                               style.width = "100%";
+                       }
+                       
+                       doc.body.appendChild(background);
+               };
+               
+               // Create the text input box form/window.
+               var createDialog = function(){
+               
+                       // The main dialog box.
+                       dialog = doc.createElement("div");
+                       dialog.className = "wmd-prompt-dialog";
+                       dialog.style.padding = "10px;";
+                       dialog.style.position = "fixed";
+                       dialog.style.width = "400px";
+                       dialog.style.zIndex = "1001";
+                       
+                       // The dialog text.
+                       var question = doc.createElement("div");
+                       question.innerHTML = text;
+                       question.style.padding = "5px";
+                       dialog.appendChild(question);
+                       
+                       // The web form container for the text box and buttons.
+                       var form = doc.createElement("form");
+                       form.onsubmit = function(){ return close(false); };
+                       style = form.style;
+                       style.padding = "0";
+                       style.margin = "0";
+                       style.cssFloat = "left";
+                       style.width = "100%";
+                       style.textAlign = "center";
+                       style.position = "relative";
+                       dialog.appendChild(form);
+                       
+                       // The input text box
+                       input = doc.createElement("input");
+            if(type == 1){
+                input.id = "image-url";
+            }
+                       input.type = "text";
+                       input.value = defaultInputText;
+                       style = input.style;
+                       style.display = "block";
+                       style.width = "80%";
+                       style.marginLeft = style.marginRight = "auto";
+                       form.appendChild(input);
+                       
+            // The upload file input
+            if(type == 1){
+                var upload = doc.createElement("div");
+                upload.innerHTML = uploadImageHTML;
+                upload.style.padding = "5px";
+                form.appendChild(upload);
+            }
+
+                       // The ok button
+                       var okButton = doc.createElement("input");
+                       okButton.type = "button";
+                       okButton.onclick = function(){ return close(false); };
+                       okButton.value = "OK";
+                       style = okButton.style;
+                       style.margin = "10px";
+                       style.display = "inline";
+                       style.width = "7em";
+
+                       
+                       // The cancel button
+                       var cancelButton = doc.createElement("input");
+                       cancelButton.type = "button";
+                       cancelButton.onclick = function(){ return close(true); };
+                       cancelButton.value = "Cancel";
+                       style = cancelButton.style;
+                       style.margin = "10px";
+                       style.display = "inline";
+                       style.width = "7em";
+
+                       // The order of these buttons is different on macs.
+                       if (/mac/.test(nav.platform.toLowerCase())) {
+                               form.appendChild(cancelButton);
+                               form.appendChild(okButton);
+                       }
+                       else {
+                               form.appendChild(okButton);
+                               form.appendChild(cancelButton);
+                       }
+
+                       util.addEvent(doc.body, "keydown", checkEscape);
+                       dialog.style.top = "50%";
+                       dialog.style.left = "50%";
+                       dialog.style.display = "block";
+                       if(global.isIE_5or6){
+                               dialog.style.position = "absolute";
+                               dialog.style.top = doc.documentElement.scrollTop + 200 + "px";
+                               dialog.style.left = "50%";
+                       }
+                       doc.body.appendChild(dialog);
+                       
+                       // This has to be done AFTER adding the dialog to the form if you
+                       // want it to be centered.
+                       dialog.style.marginTop = -(position.getHeight(dialog) / 2) + "px";
+                       dialog.style.marginLeft = -(position.getWidth(dialog) / 2) + "px";
+                       
+               };
+               
+               createBackground();
+               
+               // Why is this in a zero-length timeout?
+               // Is it working around a browser bug?
+               top.setTimeout(function(){
+               
+                       createDialog();
+
+                       var defTextLen = defaultInputText.length;
+                       if (input.selectionStart !== undefined) {
+                               input.selectionStart = 0;
+                               input.selectionEnd = defTextLen;
+                       }
+                       else if (input.createTextRange) {
+                               var range = input.createTextRange();
+                               range.collapse(false);
+                               range.moveStart("character", -defTextLen);
+                               range.moveEnd("character", defTextLen);
+                               range.select();
+                       }
+                       
+                       input.focus();
+               }, 0);
+       };
+       
+       
+       // UNFINISHED
+       // The assignment in the while loop makes jslint cranky.
+       // I'll change it to a better loop later.
+       position.getTop = function(elem, isInner){
+               var result = elem.offsetTop;
+               if (!isInner) {
+                       while (elem = elem.offsetParent) {
+                               result += elem.offsetTop;
+                       }
+               }
+               return result;
+       };
+       
+       position.getHeight = function (elem) {
+               return elem.offsetHeight || elem.scrollHeight;
+       };
+
+       position.getWidth = function (elem) {
+               return elem.offsetWidth || elem.scrollWidth;
+       };
+
+       position.getPageSize = function(){
+               
+               var scrollWidth, scrollHeight;
+               var innerWidth, innerHeight;
+               
+               // It's not very clear which blocks work with which browsers.
+               if(self.innerHeight && self.scrollMaxY){
+                       scrollWidth = doc.body.scrollWidth;
+                       scrollHeight = self.innerHeight + self.scrollMaxY;
+               }
+               else if(doc.body.scrollHeight > doc.body.offsetHeight){
+                       scrollWidth = doc.body.scrollWidth;
+                       scrollHeight = doc.body.scrollHeight;
+               }
+               else{
+                       scrollWidth = doc.body.offsetWidth;
+                       scrollHeight = doc.body.offsetHeight;
+               }
+               
+               if(self.innerHeight){
+                       // Non-IE browser
+                       innerWidth = self.innerWidth;
+                       innerHeight = self.innerHeight;
+               }
+               else if(doc.documentElement && doc.documentElement.clientHeight){
+                       // Some versions of IE (IE 6 w/ a DOCTYPE declaration)
+                       innerWidth = doc.documentElement.clientWidth;
+                       innerHeight = doc.documentElement.clientHeight;
+               }
+               else if(doc.body){
+                       // Other versions of IE
+                       innerWidth = doc.body.clientWidth;
+                       innerHeight = doc.body.clientHeight;
+               }
+               
+        var maxWidth = Math.max(scrollWidth, innerWidth);
+        var maxHeight = Math.max(scrollHeight, innerHeight);
+        return [maxWidth, maxHeight, innerWidth, innerHeight];
+       };
+       
+       // Watches the input textarea, polling at an interval and runs
+       // a callback function if anything has changed.
+       wmd.inputPoller = function(callback, interval){
+       
+               var pollerObj = this;
+               var inputArea = wmd.panels.input;
+               
+               // Stored start, end and text.  Used to see if there are changes to the input.
+               var lastStart;
+               var lastEnd;
+               var markdown;
+               
+               var killHandle; // Used to cancel monitoring on destruction.
+               // Checks to see if anything has changed in the textarea.
+               // If so, it runs the callback.
+               this.tick = function(){
+               
+                       if (!util.isVisible(inputArea)) {
+                               return;
+                       }
+                       
+                       // Update the selection start and end, text.
+                       if (inputArea.selectionStart || inputArea.selectionStart === 0) {
+                               var start = inputArea.selectionStart;
+                               var end = inputArea.selectionEnd;
+                               if (start != lastStart || end != lastEnd) {
+                                       lastStart = start;
+                                       lastEnd = end;
+                                       
+                                       if (markdown != inputArea.value) {
+                                               markdown = inputArea.value;
+                                               return true;
+                                       }
+                               }
+                       }
+                       return false;
+               };
+               
+               
+               var doTickCallback = function(){
+               
+                       if (!util.isVisible(inputArea)) {
+                               return;
+                       }
+                       
+                       // If anything has changed, call the function.
+                       if (pollerObj.tick()) {
+                               callback();
+                       }
+               };
+               
+               // Set how often we poll the textarea for changes.
+               var assignInterval = function(){
+                       // previewPollInterval is set at the top of the namespace.
+                       killHandle = top.setInterval(doTickCallback, interval);
+               };
+               
+               this.destroy = function(){
+                       top.clearInterval(killHandle);
+               };
+               
+               assignInterval();
+       };
+       
+       // Handles pushing and popping TextareaStates for undo/redo commands.
+       // I should rename the stack variables to list.
+       wmd.undoManager = function(callback){
+       
+               var undoObj = this;
+               var undoStack = []; // A stack of undo states
+               var stackPtr = 0; // The index of the current state
+               var mode = "none";
+               var lastState; // The last state
+               var poller;
+               var timer; // The setTimeout handle for cancelling the timer
+               var inputStateObj;
+               
+               // Set the mode for later logic steps.
+               var setMode = function(newMode, noSave){
+               
+                       if (mode != newMode) {
+                               mode = newMode;
+                               if (!noSave) {
+                                       saveState();
+                               }
+                       }
+                       
+                       if (!global.isIE || mode != "moving") {
+                               timer = top.setTimeout(refreshState, 1);
+                       }
+                       else {
+                               inputStateObj = null;
+                       }
+               };
+               
+               var refreshState = function(){
+                       inputStateObj = new wmd.TextareaState();
+                       poller.tick();
+                       timer = undefined;
+               };
+               
+               this.setCommandMode = function(){
+                       mode = "command";
+                       saveState();
+                       timer = top.setTimeout(refreshState, 0);
+               };
+               
+               this.canUndo = function(){
+                       return stackPtr > 1;
+               };
+               
+               this.canRedo = function(){
+                       if (undoStack[stackPtr + 1]) {
+                               return true;
+                       }
+                       return false;
+               };
+               
+               // Removes the last state and restores it.
+               this.undo = function(){
+               
+                       if (undoObj.canUndo()) {
+                               if (lastState) {
+                                       // What about setting state -1 to null or checking for undefined?
+                                       lastState.restore();
+                                       lastState = null;
+                               }
+                               else {
+                                       undoStack[stackPtr] = new wmd.TextareaState();
+                                       undoStack[--stackPtr].restore();
+                                       
+                                       if (callback) {
+                                               callback();
+                                       }
+                               }
+                       }
+                       
+                       mode = "none";
+                       wmd.panels.input.focus();
+                       refreshState();
+               };
+               
+               // Redo an action.
+               this.redo = function(){
+               
+                       if (undoObj.canRedo()) {
+                       
+                               undoStack[++stackPtr].restore();
+                               
+                               if (callback) {
+                                       callback();
+                               }
+                       }
+                       
+                       mode = "none";
+                       wmd.panels.input.focus();
+                       refreshState();
+               };
+               
+               // Push the input area state to the stack.
+               var saveState = function(){
+               
+                       var currState = inputStateObj || new wmd.TextareaState();
+                       
+                       if (!currState) {
+                               return false;
+                       }
+                       if (mode == "moving") {
+                               if (!lastState) {
+                                       lastState = currState;
+                               }
+                               return;
+                       }
+                       if (lastState) {
+                               if (undoStack[stackPtr - 1].text != lastState.text) {
+                                       undoStack[stackPtr++] = lastState;
+                               }
+                               lastState = null;
+                       }
+                       undoStack[stackPtr++] = currState;
+                       undoStack[stackPtr + 1] = null;
+                       if (callback) {
+                               callback();
+                       }
+               };
+               
+               var handleCtrlYZ = function(event){
+               
+                       var handled = false;
+                       
+                       if (event.ctrlKey || event.metaKey) {
+                       
+                               // IE and Opera do not support charCode.
+                               var keyCode = event.charCode || event.keyCode;
+                               var keyCodeChar = String.fromCharCode(keyCode);
+                               
+                               switch (keyCodeChar) {
+                               
+                                       case "y":
+                                               undoObj.redo();
+                                               handled = true;
+                                               break;
+                                               
+                                       case "z":
+                                               if (!event.shiftKey) {
+                                                       undoObj.undo();
+                                               }
+                                               else {
+                                                       undoObj.redo();
+                                               }
+                                               handled = true;
+                                               break;
+                               }
+                       }
+                       
+                       if (handled) {
+                               if (event.preventDefault) {
+                                       event.preventDefault();
+                               }
+                               if (top.event) {
+                                       top.event.returnValue = false;
+                               }
+                               return;
+                       }
+               };
+               
+               // Set the mode depending on what is going on in the input area.
+               var handleModeChange = function(event){
+               
+                       if (!event.ctrlKey && !event.metaKey) {
+                       
+                               var keyCode = event.keyCode;
+                               
+                               if ((keyCode >= 33 && keyCode <= 40) || (keyCode >= 63232 && keyCode <= 63235)) {
+                                       // 33 - 40: page up/dn and arrow keys
+                                       // 63232 - 63235: page up/dn and arrow keys on safari
+                                       setMode("moving");
+                               }
+                               else if (keyCode == 8 || keyCode == 46 || keyCode == 127) {
+                                       // 8: backspace
+                                       // 46: delete
+                                       // 127: delete
+                                       setMode("deleting");
+                               }
+                               else if (keyCode == 13) {
+                                       // 13: Enter
+                                       setMode("newlines");
+                               }
+                               else if (keyCode == 27) {
+                                       // 27: escape
+                                       setMode("escape");
+                               }
+                               else if ((keyCode < 16 || keyCode > 20) && keyCode != 91) {
+                                       // 16-20 are shift, etc. 
+                                       // 91: left window key
+                                       // I think this might be a little messed up since there are
+                                       // a lot of nonprinting keys above 20.
+                                       setMode("typing");
+                               }
+                       }
+               };
+               
+               var setEventHandlers = function(){
+               
+                       util.addEvent(wmd.panels.input, "keypress", function(event){
+                               // keyCode 89: y
+                               // keyCode 90: z
+                               if ((event.ctrlKey || event.metaKey) && (event.keyCode == 89 || event.keyCode == 90)) {
+                                       event.preventDefault();
+                               }
+                       });
+                       
+                       var handlePaste = function(){
+                               if (global.isIE || (inputStateObj && inputStateObj.text != wmd.panels.input.value)) {
+                                       if (timer == undefined) {
+                                               mode = "paste";
+                                               saveState();
+                                               refreshState();
+                                       }
+                               }
+                       };
+                       
+                       // pastePollInterval is specified at the beginning of this namespace.
+                       poller = new wmd.inputPoller(handlePaste, pastePollInterval);
+                       
+                       util.addEvent(wmd.panels.input, "keydown", handleCtrlYZ);
+                       util.addEvent(wmd.panels.input, "keydown", handleModeChange);
+                       
+                       util.addEvent(wmd.panels.input, "mousedown", function(){
+                               setMode("moving");
+                       });
+                       wmd.panels.input.onpaste = handlePaste;
+                       wmd.panels.input.ondrop = handlePaste;
+               };
+               
+               var init = function(){
+                       setEventHandlers();
+                       refreshState();
+                       saveState();
+               };
+               
+               this.destroy = function(){
+                       if (poller) {
+                               poller.destroy();
+                       }
+               };
+               
+               init();
+       };
+       
+       // I think my understanding of how the buttons and callbacks are stored in the array is incomplete.
+       wmd.editor = function(previewRefreshCallback){
+       
+               if (!previewRefreshCallback) {
+                       previewRefreshCallback = function(){};
+               }
+               
+               var inputBox = wmd.panels.input;
+               
+               var offsetHeight = 0;
+               
+               var editObj = this;
+               
+               var mainDiv;
+               var mainSpan;
+               
+               var div; // This name is pretty ambiguous.  I should rename this.
+               
+               // Used to cancel recurring events from setInterval.
+               var creationHandle;
+               
+               var undoMgr; // The undo manager
+               
+               // Perform the button's action.
+               var doClick = function(button){
+               
+                       inputBox.focus();
+                       
+                       if (button.textOp) {
+                               
+                               if (undoMgr) {
+                                       undoMgr.setCommandMode();
+                               }
+                               
+                               var state = new wmd.TextareaState();
+                               
+                               if (!state) {
+                                       return;
+                               }
+                               
+                               var chunks = state.getChunks();
+                               
+                               // Some commands launch a "modal" prompt dialog.  Javascript
+                               // can't really make a modal dialog box and the WMD code
+                               // will continue to execute while the dialog is displayed.
+                               // This prevents the dialog pattern I'm used to and means
+                               // I can't do something like this:
+                               //
+                               // var link = CreateLinkDialog();
+                               // makeMarkdownLink(link);
+                               // 
+                               // Instead of this straightforward method of handling a
+                               // dialog I have to pass any code which would execute
+                               // after the dialog is dismissed (e.g. link creation)
+                               // in a function parameter.
+                               //
+                               // Yes this is awkward and I think it sucks, but there's
+                               // no real workaround.  Only the image and link code
+                               // create dialogs and require the function pointers.
+                               var fixupInputArea = function(){
+                               
+                                       inputBox.focus();
+                                       
+                                       if (chunks) {
+                                               state.setChunks(chunks);
+                                       }
+                                       
+                                       state.restore();
+                                       previewRefreshCallback();
+                               };
+                               
+                               var useDefaultText = true;
+                               var noCleanup = button.textOp(chunks, fixupInputArea, useDefaultText);
+                               
+                               if(!noCleanup) {
+                                       fixupInputArea();
+                               }
+                               
+                       }
+                       
+                       if (button.execute) {
+                               button.execute(editObj);
+                       }
+               };
+                       
+               var setUndoRedoButtonStates = function(){
+                       if(undoMgr){
+                               setupButton(document.getElementById("wmd-undo-button"), undoMgr.canUndo());
+                               setupButton(document.getElementById("wmd-redo-button"), undoMgr.canRedo());
+                       }
+               };
+               
+               var setupButton = function(button, isEnabled) {
+               
+                       var normalYShift = "0px";
+                       var disabledYShift = "-20px";
+                       var highlightYShift = "-40px";
+                       
+                       if(isEnabled) {
+                               button.style.backgroundPosition = button.XShift + " " + normalYShift;
+                               button.onmouseover = function(){
+                                       this.style.backgroundPosition = this.XShift + " " + highlightYShift;
+                               };
+                                                       
+                               button.onmouseout = function(){
+                                       this.style.backgroundPosition = this.XShift + " " + normalYShift;
+                               };
+                               
+                               // IE tries to select the background image "button" text (it's
+                               // implemented in a list item) so we have to cache the selection
+                               // on mousedown.
+                               if(global.isIE) {
+                                       button.onmousedown =  function() { 
+                                               wmd.ieRetardedClick = true;
+                                               wmd.ieCachedRange = document.selection.createRange(); 
+                                       };
+                               }
+                               
+                               if (!button.isHelp)
+                               {
+                                       button.onclick = function() {
+                                               if (this.onmouseout) {
+                                                       this.onmouseout();
+                                               }
+                                               doClick(this);
+                                               return false;
+                                       }
+                               }
+                       }
+                       else {
+                               button.style.backgroundPosition = button.XShift + " " + disabledYShift;
+                               button.onmouseover = button.onmouseout = button.onclick = function(){};
+                       }
+               }
+       
+               var makeSpritedButtonRow = function(){
+                       
+                       var buttonBar = document.getElementById("wmd-button-bar");
+       
+                       var normalYShift = "0px";
+                       var disabledYShift = "-20px";
+                       var highlightYShift = "-40px";
+                       
+                       var buttonRow = document.createElement("ul");
+                       buttonRow.id = "wmd-button-row";
+                       buttonRow = buttonBar.appendChild(buttonRow);
+
+                       
+                       var boldButton = document.createElement("li");
+                       boldButton.className = "wmd-button";
+                       boldButton.id = "wmd-bold-button";
+                       boldButton.title = toolbar_strong_label;
+                       boldButton.XShift = "0px";
+                       boldButton.textOp = command.doBold;
+                       setupButton(boldButton, true);
+                       buttonRow.appendChild(boldButton);
+                       
+                       var italicButton = document.createElement("li");
+                       italicButton.className = "wmd-button";
+                       italicButton.id = "wmd-italic-button";
+                       italicButton.title = toolbar_emphasis_label;
+                       italicButton.XShift = "-20px";
+                       italicButton.textOp = command.doItalic;
+                       setupButton(italicButton, true);
+                       buttonRow.appendChild(italicButton);
+
+                       var spacer1 = document.createElement("li");
+                       spacer1.className = "wmd-spacer";
+                       spacer1.id = "wmd-spacer1";
+                       buttonRow.appendChild(spacer1); 
+
+                       var linkButton = document.createElement("li");
+                       linkButton.className = "wmd-button";
+                       linkButton.id = "wmd-link-button";
+                       linkButton.title = toolbar_hyperlink_label;
+                       linkButton.XShift = "-40px";
+                       linkButton.textOp = function(chunk, postProcessing, useDefaultText){
+                               return command.doLinkOrImage(chunk, postProcessing, false);
+                       };
+                       setupButton(linkButton, true);
+                       buttonRow.appendChild(linkButton);
+
+                       var quoteButton = document.createElement("li");
+                       quoteButton.className = "wmd-button";
+                       quoteButton.id = "wmd-quote-button";
+                       quoteButton.title = toolbar_blockquote_label;
+                       quoteButton.XShift = "-60px";
+                       quoteButton.textOp = command.doBlockquote;
+                       setupButton(quoteButton, true);
+                       buttonRow.appendChild(quoteButton);
+                       
+                       var codeButton = document.createElement("li");
+                       codeButton.className = "wmd-button";
+                       codeButton.id = "wmd-code-button";
+                       codeButton.title = toolbar_code_label;
+                       codeButton.XShift = "-80px";
+                       codeButton.textOp = command.doCode;
+                       setupButton(codeButton, true);
+                       buttonRow.appendChild(codeButton);
+
+                       var imageButton = document.createElement("li");
+                       imageButton.className = "wmd-button";
+                       imageButton.id = "wmd-image-button";
+                       imageButton.title = toolbar_image_label;
+                       imageButton.XShift = "-100px";
+                       imageButton.textOp = function(chunk, postProcessing, useDefaultText){
+                               return command.doLinkOrImage(chunk, postProcessing, true);
+                       };
+                       setupButton(imageButton, true);
+                       buttonRow.appendChild(imageButton);
+
+                       var spacer2 = document.createElement("li");
+                       spacer2.className = "wmd-spacer";
+                       spacer2.id = "wmd-spacer2";
+                       buttonRow.appendChild(spacer2); 
+
+                       var olistButton = document.createElement("li");
+                       olistButton.className = "wmd-button";
+                       olistButton.id = "wmd-olist-button";
+                       olistButton.title = toolbar_numbered_label;
+                       olistButton.XShift = "-120px";
+                       olistButton.textOp = function(chunk, postProcessing, useDefaultText){
+                               command.doList(chunk, postProcessing, true, useDefaultText);
+                       };
+                       setupButton(olistButton, true);
+                       buttonRow.appendChild(olistButton);
+                       
+                       var ulistButton = document.createElement("li");
+                       ulistButton.className = "wmd-button";
+                       ulistButton.id = "wmd-ulist-button";
+                       ulistButton.title = toolbar_bulleted_label;
+                       ulistButton.XShift = "-140px";
+                       ulistButton.textOp = function(chunk, postProcessing, useDefaultText){
+                               command.doList(chunk, postProcessing, false, useDefaultText);
+                       };
+                       setupButton(ulistButton, true);
+                       buttonRow.appendChild(ulistButton);
+                       
+                       var headingButton = document.createElement("li");
+                       headingButton.className = "wmd-button";
+                       headingButton.id = "wmd-heading-button";
+                       headingButton.title = toolbar_heading_label;
+                       headingButton.XShift = "-160px";
+                       headingButton.textOp = command.doHeading;
+                       setupButton(headingButton, true);
+                       buttonRow.appendChild(headingButton); 
+                       
+                       var hrButton = document.createElement("li");
+                       hrButton.className = "wmd-button";
+                       hrButton.id = "wmd-hr-button";
+                       hrButton.title = toolbar_horizontal_label;
+                       hrButton.XShift = "-180px";
+                       hrButton.textOp = command.doHorizontalRule;
+                       setupButton(hrButton, true);
+                       buttonRow.appendChild(hrButton); 
+                       
+                       var spacer3 = document.createElement("li");
+                       spacer3.className = "wmd-spacer";
+                       spacer3.id = "wmd-spacer3";
+                       buttonRow.appendChild(spacer3); 
+                       
+                       var undoButton = document.createElement("li");
+                       undoButton.className = "wmd-button";
+                       undoButton.id = "wmd-undo-button";
+                       undoButton.title = toolbar_undo_label;
+                       undoButton.XShift = "-200px";
+                       undoButton.execute = function(manager){
+                               manager.undo();
+                       };
+                       setupButton(undoButton, true);
+                       buttonRow.appendChild(undoButton); 
+                       
+                       var redoButton = document.createElement("li");
+                       redoButton.className = "wmd-button";
+                       redoButton.id = "wmd-redo-button";
+                       redoButton.title = toolbar_redo_label;
+                       if (/win/.test(nav.platform.toLowerCase())) {
+                               redoButton.title = toolbar_redo_label;
+                       }
+                       else {
+                               // mac and other non-Windows platforms
+                               redoButton.title = $.i18n._('redo') + " - Ctrl+Shift+Z";
+                       }
+                       redoButton.XShift = "-220px";
+                       redoButton.execute = function(manager){
+                               manager.redo();
+                       };
+                       setupButton(redoButton, true);
+                       buttonRow.appendChild(redoButton); 
+                       
+                       setUndoRedoButtonStates();
+               }
+               
+               var setupEditor = function(){
+               
+                       if (/\?noundo/.test(doc.location.href)) {
+                               wmd.nativeUndo = true;
+                       }
+                       
+                       if (!wmd.nativeUndo) {
+                               undoMgr = new wmd.undoManager(function(){
+                                       previewRefreshCallback();
+                                       setUndoRedoButtonStates();
+                               });
+                       }
+                       
+                       makeSpritedButtonRow();
+                       
+                       
+                       var keyEvent = "keydown";
+                       if (global.isOpera) {
+                               keyEvent = "keypress";
+                       }
+                       
+                       util.addEvent(inputBox, keyEvent, function(key){
+                               
+                               // Check to see if we have a button key and, if so execute the callback.
+                               if (key.ctrlKey || key.metaKey) {
+                       
+                                       var keyCode = key.charCode || key.keyCode;
+                                       var keyCodeStr = String.fromCharCode(keyCode).toLowerCase();
+                                       
+                                       // Bugfix for messed up DEL and .
+                                       if (keyCode === 46) {
+                                               keyCodeStr = "";
+                                       }
+                                       if (keyCode === 190) {
+                                               keyCodeStr = ".";
+                                       }
+
+                                       switch(keyCodeStr) {
+                                               case "b":
+                                                       doClick(document.getElementById("wmd-bold-button"));
+                                                       break;
+                                               case "i":
+                                                       doClick(document.getElementById("wmd-italic-button"));
+                                                       break;
+                                               case "l":
+                                                       doClick(document.getElementById("wmd-link-button"));
+                                                       break;
+                                               case "q":
+                                                       doClick(document.getElementById("wmd-quote-button"));
+                                                       break;
+                                               case "k":
+                                                       doClick(document.getElementById("wmd-code-button"));
+                                                       break;
+                                               case "g":
+                                                       doClick(document.getElementById("wmd-image-button"));
+                                                       break;
+                                               case "o":
+                                                       doClick(document.getElementById("wmd-olist-button"));
+                                                       break;
+                                               case "u":
+                                                       doClick(document.getElementById("wmd-ulist-button"));
+                                                       break;
+                                               case "h":
+                                                       doClick(document.getElementById("wmd-heading-button"));
+                                                       break;
+                                               case "r":
+                                                       doClick(document.getElementById("wmd-hr-button"));
+                                                       break;
+                                               case "y":
+                                                       doClick(document.getElementById("wmd-redo-button"));
+                                                       break;
+                                               case "z":
+                                                       if(key.shiftKey) {
+                                                               doClick(document.getElementById("wmd-redo-button"));
+                                                       }
+                                                       else {
+                                                               doClick(document.getElementById("wmd-undo-button"));
+                                                       }
+                                                       break;
+                                               default:
+                                                       return;
+                                       }
+                                       
+
+                                       if (key.preventDefault) {
+                                               key.preventDefault();
+                                       }
+                                       
+                                       if (top.event) {
+                                               top.event.returnValue = false;
+                                       }
+                               }
+                       });
+                       
+                       // Auto-continue lists, code blocks and block quotes when
+                       // the enter key is pressed.
+                       util.addEvent(inputBox, "keyup", function(key){
+                               if (!key.shiftKey && !key.ctrlKey && !key.metaKey) {
+                                       var keyCode = key.charCode || key.keyCode;
+                                       // Key code 13 is Enter
+                                       if (keyCode === 13) {
+                                               fakeButton = {};
+                                               fakeButton.textOp = command.doAutoindent;
+                                               doClick(fakeButton);
+                                       }
+                               }
+                       });
+                       
+                       // Disable ESC clearing the input textarea on IE
+                       if (global.isIE) {
+                               util.addEvent(inputBox, "keydown", function(key){
+                                       var code = key.keyCode;
+                                       // Key code 27 is ESC
+                                       if (code === 27) {
+                                               return false;
+                                       }
+                               });
+                       }
+                       
+                       if (inputBox.form) {
+                               var submitCallback = inputBox.form.onsubmit;
+                               inputBox.form.onsubmit = function(){
+                                       convertToHtml();
+                                       if (submitCallback) {
+                                               return submitCallback.apply(this, arguments);
+                                       }
+                               };
+                       }
+               };
+               
+               // Convert the contents of the input textarea to HTML in the output/preview panels.
+               var convertToHtml = function(){
+               
+                       if (wmd.showdown) {
+                               var markdownConverter = new wmd.showdown.converter();
+                       }
+                       var text = inputBox.value;
+                       
+                       var callback = function(){
+                               inputBox.value = text;
+                       };
+                       
+                       if (!/markdown/.test(wmd.wmd_env.output.toLowerCase())) {
+                               if (markdownConverter) {
+                                       inputBox.value = markdownConverter.makeHtml(text);
+                                       top.setTimeout(callback, 0);
+                               }
+                       }
+                       return true;
+               };
+               
+               
+               this.undo = function(){
+                       if (undoMgr) {
+                               undoMgr.undo();
+                       }
+               };
+               
+               this.redo = function(){
+                       if (undoMgr) {
+                               undoMgr.redo();
+                       }
+               };
+               
+               // This is pretty useless.  The setupEditor function contents
+               // should just be copied here.
+               var init = function(){
+                       setupEditor();
+               };
+               
+               this.destroy = function(){
+                       if (undoMgr) {
+                               undoMgr.destroy();
+                       }
+                       if (div.parentNode) {
+                               div.parentNode.removeChild(div);
+                       }
+                       if (inputBox) {
+                               inputBox.style.marginTop = "";
+                       }
+                       top.clearInterval(creationHandle);
+               };
+               
+               init();
+       };
+       
+       // The input textarea state/contents.
+       // This is used to implement undo/redo by the undo manager.
+       wmd.TextareaState = function(){
+       
+               // Aliases
+               var stateObj = this;
+               var inputArea = wmd.panels.input;
+               
+               this.init = function() {
+               
+                       if (!util.isVisible(inputArea)) {
+                               return;
+                       }
+                               
+                       this.setInputAreaSelectionStartEnd();
+                       this.scrollTop = inputArea.scrollTop;
+                       if (!this.text && inputArea.selectionStart || inputArea.selectionStart === 0) {
+                               this.text = inputArea.value;
+                       }
+                       
+               };
+               
+               // Sets the selected text in the input box after we've performed an
+               // operation.
+               this.setInputAreaSelection = function(){
+               
+                       if (!util.isVisible(inputArea)) {
+                               return;
+                       }
+                       
+                       if (inputArea.selectionStart !== undefined && !global.isOpera) {
+                       
+                               inputArea.focus();
+                               inputArea.selectionStart = stateObj.start;
+                               inputArea.selectionEnd = stateObj.end;
+                               inputArea.scrollTop = stateObj.scrollTop;
+                       }
+                       else if (doc.selection) {
+                               
+                               if (doc.activeElement && doc.activeElement !== inputArea) {
+                                       return;
+                               }
+                                       
+                               inputArea.focus();
+                               var range = inputArea.createTextRange();
+                               range.moveStart("character", -inputArea.value.length);
+                               range.moveEnd("character", -inputArea.value.length);
+                               range.moveEnd("character", stateObj.end);
+                               range.moveStart("character", stateObj.start);
+                               range.select();
+                       }
+               };
+               
+               this.setInputAreaSelectionStartEnd = function(){
+               
+                       if (inputArea.selectionStart || inputArea.selectionStart === 0) {
+                       
+                               stateObj.start = inputArea.selectionStart;
+                               stateObj.end = inputArea.selectionEnd;
+                       }
+                       else if (doc.selection) {
+                               
+                               stateObj.text = util.fixEolChars(inputArea.value);
+                               
+                               // IE loses the selection in the textarea when buttons are
+                               // clicked.  On IE we cache the selection and set a flag
+                               // which we check for here.
+                               var range;
+                               if(wmd.ieRetardedClick && wmd.ieCachedRange) {
+                                       range = wmd.ieCachedRange;
+                                       wmd.ieRetardedClick = false;
+                               }
+                               else {
+                                       range = doc.selection.createRange();
+                               }
+
+                               var fixedRange = util.fixEolChars(range.text);
+                               var marker = "\x07";
+                               var markedRange = marker + fixedRange + marker;
+                               range.text = markedRange;
+                               var inputText = util.fixEolChars(inputArea.value);
+                                       
+                               range.moveStart("character", -markedRange.length);
+                               range.text = fixedRange;
+
+                               stateObj.start = inputText.indexOf(marker);
+                               stateObj.end = inputText.lastIndexOf(marker) - marker.length;
+                                       
+                               var len = stateObj.text.length - util.fixEolChars(inputArea.value).length;
+                                       
+                               if (len) {
+                                       range.moveStart("character", -fixedRange.length);
+                                       while (len--) {
+                                               fixedRange += "\n";
+                                               stateObj.end += 1;
+                                       }
+                                       range.text = fixedRange;
+                               }
+                                       
+                               this.setInputAreaSelection();
+                       }
+               };
+               
+               // Restore this state into the input area.
+               this.restore = function(){
+               
+                       if (stateObj.text != undefined && stateObj.text != inputArea.value) {
+                               inputArea.value = stateObj.text;
+                       }
+                       this.setInputAreaSelection();
+                       inputArea.scrollTop = stateObj.scrollTop;
+               };
+               
+               // Gets a collection of HTML chunks from the inptut textarea.
+               this.getChunks = function(){
+               
+                       var chunk = new wmd.Chunks();
+                       
+                       chunk.before = util.fixEolChars(stateObj.text.substring(0, stateObj.start));
+                       chunk.startTag = "";
+                       chunk.selection = util.fixEolChars(stateObj.text.substring(stateObj.start, stateObj.end));
+                       chunk.endTag = "";
+                       chunk.after = util.fixEolChars(stateObj.text.substring(stateObj.end));
+                       chunk.scrollTop = stateObj.scrollTop;
+                       
+                       return chunk;
+               };
+               
+               // Sets the TextareaState properties given a chunk of markdown.
+               this.setChunks = function(chunk){
+               
+                       chunk.before = chunk.before + chunk.startTag;
+                       chunk.after = chunk.endTag + chunk.after;
+                       
+                       if (global.isOpera) {
+                               chunk.before = chunk.before.replace(/\n/g, "\r\n");
+                               chunk.selection = chunk.selection.replace(/\n/g, "\r\n");
+                               chunk.after = chunk.after.replace(/\n/g, "\r\n");
+                       }
+                       
+                       this.start = chunk.before.length;
+                       this.end = chunk.before.length + chunk.selection.length;
+                       this.text = chunk.before + chunk.selection + chunk.after;
+                       this.scrollTop = chunk.scrollTop;
+               };
+
+               this.init();
+       };
+       
+       // before: contains all the text in the input box BEFORE the selection.
+       // after: contains all the text in the input box AFTER the selection.
+       wmd.Chunks = function(){
+       };
+       
+       // startRegex: a regular expression to find the start tag
+       // endRegex: a regular expresssion to find the end tag
+       wmd.Chunks.prototype.findTags = function(startRegex, endRegex){
+       
+               var chunkObj = this;
+               var regex;
+               
+               if (startRegex) {
+                       
+                       regex = util.extendRegExp(startRegex, "", "$");
+                       
+                       this.before = this.before.replace(regex, 
+                               function(match){
+                                       chunkObj.startTag = chunkObj.startTag + match;
+                                       return "";
+                               });
+                       
+                       regex = util.extendRegExp(startRegex, "^", "");
+                       
+                       this.selection = this.selection.replace(regex, 
+                               function(match){
+                                       chunkObj.startTag = chunkObj.startTag + match;
+                                       return "";
+                               });
+               }
+               
+               if (endRegex) {
+                       
+                       regex = util.extendRegExp(endRegex, "", "$");
+                       
+                       this.selection = this.selection.replace(regex,
+                               function(match){
+                                       chunkObj.endTag = match + chunkObj.endTag;
+                                       return "";
+                               });
+
+                       regex = util.extendRegExp(endRegex, "^", "");
+                       
+                       this.after = this.after.replace(regex,
+                               function(match){
+                                       chunkObj.endTag = match + chunkObj.endTag;
+                                       return "";
+                               });
+               }
+       };
+       
+       // If remove is false, the whitespace is transferred
+       // to the before/after regions.
+       //
+       // If remove is true, the whitespace disappears.
+       wmd.Chunks.prototype.trimWhitespace = function(remove){
+       
+               this.selection = this.selection.replace(/^(\s*)/, "");
+               
+               if (!remove) {
+                       this.before += re.$1;
+               }
+               
+               this.selection = this.selection.replace(/(\s*)$/, "");
+               
+               if (!remove) {
+                       this.after = re.$1 + this.after;
+               }
+       };
+       
+       
+       wmd.Chunks.prototype.addBlankLines = function(nLinesBefore, nLinesAfter, findExtraNewlines){
+       
+               if (nLinesBefore === undefined) {
+                       nLinesBefore = 1;
+               }
+               
+               if (nLinesAfter === undefined) {
+                       nLinesAfter = 1;
+               }
+               
+               nLinesBefore++;
+               nLinesAfter++;
+               
+               var regexText;
+               var replacementText;
+               
+               this.selection = this.selection.replace(/(^\n*)/, "");
+               this.startTag = this.startTag + re.$1;
+               this.selection = this.selection.replace(/(\n*$)/, "");
+               this.endTag = this.endTag + re.$1;
+               this.startTag = this.startTag.replace(/(^\n*)/, "");
+               this.before = this.before + re.$1;
+               this.endTag = this.endTag.replace(/(\n*$)/, "");
+               this.after = this.after + re.$1;
+               
+               if (this.before) {
+               
+                       regexText = replacementText = "";
+                       
+                       while (nLinesBefore--) {
+                               regexText += "\\n?";
+                               replacementText += "\n";
+                       }
+                       
+                       if (findExtraNewlines) {
+                               regexText = "\\n*";
+                       }
+                       this.before = this.before.replace(new re(regexText + "$", ""), replacementText);
+               }
+               
+               if (this.after) {
+               
+                       regexText = replacementText = "";
+                       
+                       while (nLinesAfter--) {
+                               regexText += "\\n?";
+                               replacementText += "\n";
+                       }
+                       if (findExtraNewlines) {
+                               regexText = "\\n*";
+                       }
+                       
+                       this.after = this.after.replace(new re(regexText, ""), replacementText);
+               }
+       };
+       
+       // The markdown symbols - 4 spaces = code, > = blockquote, etc.
+       command.prefixes = "(?:\\s{4,}|\\s*>|\\s*-\\s+|\\s*\\d+\\.|=|\\+|-|_|\\*|#|\\s*\\[[^\n]]+\\]:)";
+       
+       // Remove markdown symbols from the chunk selection.
+       command.unwrap = function(chunk){
+               var txt = new re("([^\\n])\\n(?!(\\n|" + command.prefixes + "))", "g");
+               chunk.selection = chunk.selection.replace(txt, "$1 $2");
+       };
+       
+       command.wrap = function(chunk, len){
+               command.unwrap(chunk);
+               var regex = new re("(.{1," + len + "})( +|$\\n?)", "gm");
+               
+               chunk.selection = chunk.selection.replace(regex, function(line, marked){
+                       if (new re("^" + command.prefixes, "").test(line)) {
+                               return line;
+                       }
+                       return marked + "\n";
+               });
+               
+               chunk.selection = chunk.selection.replace(/\s+$/, "");
+       };
+       
+       command.doBold = function(chunk, postProcessing, useDefaultText){
+               return command.doBorI(chunk, 2, "strong text");
+       };
+       
+       command.doItalic = function(chunk, postProcessing, useDefaultText){
+               return command.doBorI(chunk, 1, "emphasized text");
+       };
+       
+       // chunk: The selected region that will be enclosed with */**
+       // nStars: 1 for italics, 2 for bold
+       // insertText: If you just click the button without highlighting text, this gets inserted
+       command.doBorI = function(chunk, nStars, insertText){
+       
+               // Get rid of whitespace and fixup newlines.
+               chunk.trimWhitespace();
+               chunk.selection = chunk.selection.replace(/\n{2,}/g, "\n");
+               
+               // Look for stars before and after.  Is the chunk already marked up?
+               chunk.before.search(/(\**$)/);
+               var starsBefore = re.$1;
+               
+               chunk.after.search(/(^\**)/);
+               var starsAfter = re.$1;
+               
+               var prevStars = Math.min(starsBefore.length, starsAfter.length);
+               
+               // Remove stars if we have to since the button acts as a toggle.
+               if ((prevStars >= nStars) && (prevStars != 2 || nStars != 1)) {
+                       chunk.before = chunk.before.replace(re("[*]{" + nStars + "}$", ""), "");
+                       chunk.after = chunk.after.replace(re("^[*]{" + nStars + "}", ""), "");
+               }
+               else if (!chunk.selection && starsAfter) {
+                       // It's not really clear why this code is necessary.  It just moves
+                       // some arbitrary stuff around.
+                       chunk.after = chunk.after.replace(/^([*_]*)/, "");
+                       chunk.before = chunk.before.replace(/(\s?)$/, "");
+                       var whitespace = re.$1;
+                       chunk.before = chunk.before + starsAfter + whitespace;
+               }
+               else {
+               
+                       // In most cases, if you don't have any selected text and click the button
+                       // you'll get a selected, marked up region with the default text inserted.
+                       if (!chunk.selection && !starsAfter) {
+                               chunk.selection = insertText;
+                       }
+                       
+                       // Add the true markup.
+                       var markup = nStars <= 1 ? "*" : "**"; // shouldn't the test be = ?
+                       chunk.before = chunk.before + markup;
+                       chunk.after = markup + chunk.after;
+               }
+               
+               return;
+       };
+       
+       command.stripLinkDefs = function(text, defsToAdd){
+       
+               text = text.replace(/^[ ]{0,3}\[(\d+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|$)/gm, 
+                       function(totalMatch, id, link, newlines, title){        
+                               defsToAdd[id] = totalMatch.replace(/\s*$/, "");
+                               if (newlines) {
+                                       // Strip the title and return that separately.
+                                       defsToAdd[id] = totalMatch.replace(/["(](.+?)[")]$/, "");
+                                       return newlines + title;
+                               }
+                               return "";
+                       });
+               
+               return text;
+       };
+       
+       command.addLinkDef = function(chunk, linkDef){
+       
+               var refNumber = 0; // The current reference number
+               var defsToAdd = {}; //
+               // Start with a clean slate by removing all previous link definitions.
+               chunk.before = command.stripLinkDefs(chunk.before, defsToAdd);
+               chunk.selection = command.stripLinkDefs(chunk.selection, defsToAdd);
+               chunk.after = command.stripLinkDefs(chunk.after, defsToAdd);
+               
+               var defs = "";
+               var regex = /(\[(?:\[[^\]]*\]|[^\[\]])*\][ ]?(?:\n[ ]*)?\[)(\d+)(\])/g;
+               
+               var addDefNumber = function(def){
+                       refNumber++;
+                       def = def.replace(/^[ ]{0,3}\[(\d+)\]:/, "  [" + refNumber + "]:");
+                       defs += "\n" + def;
+               };
+               
+               var getLink = function(wholeMatch, link, id, end){
+               
+                       if (defsToAdd[id]) {
+                               addDefNumber(defsToAdd[id]);
+                               return link + refNumber + end;
+                               
+                       }
+                       return wholeMatch;
+               };
+               
+               chunk.before = chunk.before.replace(regex, getLink);
+               
+               if (linkDef) {
+                       addDefNumber(linkDef);
+               }
+               else {
+                       chunk.selection = chunk.selection.replace(regex, getLink);
+               }
+               
+               var refOut = refNumber;
+               
+               chunk.after = chunk.after.replace(regex, getLink);
+               
+               if (chunk.after) {
+                       chunk.after = chunk.after.replace(/\n*$/, "");
+               }
+               if (!chunk.after) {
+                       chunk.selection = chunk.selection.replace(/\n*$/, "");
+               }
+               
+               chunk.after += "\n\n" + defs;
+               
+               return refOut;
+       };
+       
+       command.doLinkOrImage = function(chunk, postProcessing, isImage){
+       
+               chunk.trimWhitespace();
+               chunk.findTags(/\s*!?\[/, /\][ ]?(?:\n[ ]*)?(\[.*?\])?/);
+               
+               if (chunk.endTag.length > 1) {
+               
+                       chunk.startTag = chunk.startTag.replace(/!?\[/, "");
+                       chunk.endTag = "";
+                       command.addLinkDef(chunk, null);
+                       
+               }
+               else {
+               
+                       if (/\n\n/.test(chunk.selection)) {
+                               command.addLinkDef(chunk, null);
+                               return;
+                       }
+                       
+                       // The function to be executed when you enter a link and press OK or Cancel.
+                       // Marks up the link and adds the ref.
+                       var makeLinkMarkdown = function(link){
+                       
+                               if (link !== null) {
+                               
+                                       chunk.startTag = chunk.endTag = "";
+                                       var linkDef = " [999]: " + link;
+                                       
+                                       var num = command.addLinkDef(chunk, linkDef);
+                                       chunk.startTag = isImage ? "![" : "[";
+                                       chunk.endTag = "][" + num + "]";
+                                       
+                                       if (!chunk.selection) {
+                                               if (isImage) {
+                                                       chunk.selection = "alt text";
+                                               }
+                                               else {
+                                                       chunk.selection = "link text";
+                                               }
+                                       }
+                               }
+                               postProcessing();
+                       };
+                       
+                       if (isImage) {
+                // add fourth param to identify image window
+                               util.prompt(imageDialogText, imageDefaultText, makeLinkMarkdown, 1);
+                       }
+                       else {
+                               util.prompt(linkDialogText, linkDefaultText, makeLinkMarkdown);
+                       }
+                       return true;
+               }
+       };
+       
+       util.makeAPI = function(){
+               wmd.wmd = {};
+               wmd.wmd.editor = wmd.editor;
+               wmd.wmd.previewManager = wmd.previewManager;
+       };
+       
+       util.startEditor = function(){
+       
+               if (wmd.wmd_env.autostart === false) {
+                       util.makeAPI();
+                       return;
+               }
+
+               var edit;               // The editor (buttons + input + outputs) - the main object.
+               var previewMgr; // The preview manager.
+               
+               // Fired after the page has fully loaded.
+               var loadListener = function(){
+               
+                       wmd.panels = new wmd.PanelCollection();
+                       
+                       previewMgr = new wmd.previewManager();
+                       var previewRefreshCallback = previewMgr.refresh;
+                                               
+                       edit = new wmd.editor(previewRefreshCallback);
+                       
+                       previewMgr.refresh(true);
+                       
+               };
+               
+               util.addEvent(top, "load", loadListener);
+       };
+       
+       wmd.previewManager = function(){
+               
+               var managerObj = this;
+               var converter;
+               var poller;
+               var timeout;
+               var elapsedTime;
+               var oldInputText;
+               var htmlOut;
+               var maxDelay = 3000;
+               var startType = "delayed"; // The other legal value is "manual"
+               
+               // Adds event listeners to elements and creates the input poller.
+               var setupEvents = function(inputElem, listener){
+               
+                       util.addEvent(inputElem, "input", listener);
+                       inputElem.onpaste = listener;
+                       inputElem.ondrop = listener;
+                       
+                       util.addEvent(inputElem, "keypress", listener);
+                       util.addEvent(inputElem, "keydown", listener);
+                       // previewPollInterval is set at the top of this file.
+                       poller = new wmd.inputPoller(listener, previewPollInterval);
+               };
+               
+               var getDocScrollTop = function(){
+               
+                       var result = 0;
+                       
+                       if (top.innerHeight) {
+                               result = top.pageYOffset;
+                       }
+                       else 
+                               if (doc.documentElement && doc.documentElement.scrollTop) {
+                                       result = doc.documentElement.scrollTop;
+                               }
+                               else 
+                                       if (doc.body) {
+                                               result = doc.body.scrollTop;
+                                       }
+                       
+                       return result;
+               };
+               
+               var makePreviewHtml = function(){
+               
+                       // If there are no registered preview and output panels
+                       // there is nothing to do.
+                       if (!wmd.panels.preview && !wmd.panels.output) {
+                               return;
+                       }
+                       
+                       var text = wmd.panels.input.value;
+                       if (text && text == oldInputText) {
+                               return; // Input text hasn't changed.
+                       }
+                       else {
+                               oldInputText = text;
+                       }
+                       
+                       var prevTime = new Date().getTime();
+                       
+                       if (!converter && wmd.showdown) {
+                               converter = new wmd.showdown.converter();
+                       }
+                       
+                       if (converter) {
+                               text = converter.makeHtml(text);
+                       }
+                       
+                       // Calculate the processing time of the HTML creation.
+                       // It's used as the delay time in the event listener.
+                       var currTime = new Date().getTime();
+                       elapsedTime = currTime - prevTime;
+                       
+                       pushPreviewHtml(text);
+                       htmlOut = text;
+               };
+               
+               // setTimeout is already used.  Used as an event listener.
+               var applyTimeout = function(){
+               
+                       if (timeout) {
+                               top.clearTimeout(timeout);
+                               timeout = undefined;
+                       }
+                       
+                       if (startType !== "manual") {
+                       
+                               var delay = 0;
+                               
+                               if (startType === "delayed") {
+                                       delay = elapsedTime;
+                               }
+                               
+                               if (delay > maxDelay) {
+                                       delay = maxDelay;
+                               }
+                               timeout = top.setTimeout(makePreviewHtml, delay);
+                       }
+               };
+               
+               var getScaleFactor = function(panel){
+                       if (panel.scrollHeight <= panel.clientHeight) {
+                               return 1;
+                       }
+                       return panel.scrollTop / (panel.scrollHeight - panel.clientHeight);
+               };
+               
+               var setPanelScrollTops = function(){
+               
+                       if (wmd.panels.preview) {
+                               wmd.panels.preview.scrollTop = (wmd.panels.preview.scrollHeight - wmd.panels.preview.clientHeight) * getScaleFactor(wmd.panels.preview);
+                               ;
+                       }
+                       
+                       if (wmd.panels.output) {
+                               wmd.panels.output.scrollTop = (wmd.panels.output.scrollHeight - wmd.panels.output.clientHeight) * getScaleFactor(wmd.panels.output);
+                               ;
+                       }
+               };
+               
+               this.refresh = function(requiresRefresh){
+               
+                       if (requiresRefresh) {
+                               oldInputText = "";
+                               makePreviewHtml();
+                       }
+                       else {
+                               applyTimeout();
+                       }
+               };
+               
+               this.processingTime = function(){
+                       return elapsedTime;
+               };
+               
+               // The output HTML
+               this.output = function(){
+                       return htmlOut;
+               };
+               
+               // The mode can be "manual" or "delayed"
+               this.setUpdateMode = function(mode){
+                       startType = mode;
+                       managerObj.refresh();
+               };
+               
+               var isFirstTimeFilled = true;
+               
+               var pushPreviewHtml = function(text){
+               
+                       var emptyTop = position.getTop(wmd.panels.input) - getDocScrollTop();
+                       
+                       // Send the encoded HTML to the output textarea/div.
+                       if (wmd.panels.output) {
+                               // The value property is only defined if the output is a textarea.
+                               if (wmd.panels.output.value !== undefined) {
+                                       wmd.panels.output.value = text;
+                                       wmd.panels.output.readOnly = true;
+                               }
+                               // Otherwise we are just replacing the text in a div.
+                               // Send the HTML wrapped in <pre><code>
+                               else {
+                                       var newText = text.replace(/&/g, "&amp;");
+                                       newText = newText.replace(/</g, "&lt;");
+                                       wmd.panels.output.innerHTML = "<pre><code>" + newText + "</code></pre>";
+                               }
+                       }
+                       
+                       if (wmd.panels.preview) {
+                               wmd.panels.preview.innerHTML = text;
+                       }
+                       
+                       setPanelScrollTops();
+                       
+                       if (isFirstTimeFilled) {
+                               isFirstTimeFilled = false;
+                               return;
+                       }
+                       
+                       var fullTop = position.getTop(wmd.panels.input) - getDocScrollTop();
+                       
+                       if (global.isIE) {
+                               top.setTimeout(function(){
+                                       top.scrollBy(0, fullTop - emptyTop);
+                               }, 0);
+                       }
+                       else {
+                               top.scrollBy(0, fullTop - emptyTop);
+                       }
+               };
+               
+               var init = function(){
+               
+                       setupEvents(wmd.panels.input, applyTimeout);
+                       makePreviewHtml();
+                       
+                       if (wmd.panels.preview) {
+                               wmd.panels.preview.scrollTop = 0;
+                       }
+                       if (wmd.panels.output) {
+                               wmd.panels.output.scrollTop = 0;
+                       }
+               };
+               
+               this.destroy = function(){
+                       if (poller) {
+                               poller.destroy();
+                       }
+               };
+               
+               init();
+       };
+
+       // Moves the cursor to the next line and continues lists, quotes and code.
+       command.doAutoindent = function(chunk, postProcessing, useDefaultText){
+               
+               chunk.before = chunk.before.replace(/(\n|^)[ ]{0,3}([*+-]|\d+[.])[ \t]*\n$/, "\n\n");
+               chunk.before = chunk.before.replace(/(\n|^)[ ]{0,3}>[ \t]*\n$/, "\n\n");
+               chunk.before = chunk.before.replace(/(\n|^)[ \t]+\n$/, "\n\n");
+               
+               useDefaultText = false;
+               
+               if(/(\n|^)[ ]{0,3}([*+-])[ \t]+.*\n$/.test(chunk.before)){
+                       if(command.doList){
+                               command.doList(chunk, postProcessing, false, true);
+                       }
+               }
+               if(/(\n|^)[ ]{0,3}(\d+[.])[ \t]+.*\n$/.test(chunk.before)){
+                       if(command.doList){
+                               command.doList(chunk, postProcessing, true, true);
+                       }
+               }
+               if(/(\n|^)[ ]{0,3}>[ \t]+.*\n$/.test(chunk.before)){
+                       if(command.doBlockquote){
+                               command.doBlockquote(chunk, postProcessing, useDefaultText);
+                       }
+               }
+               if(/(\n|^)(\t|[ ]{4,}).*\n$/.test(chunk.before)){
+                       if(command.doCode){
+                               command.doCode(chunk, postProcessing, useDefaultText);
+                       }
+               }
+       };
+       
+       command.doBlockquote = function(chunk, postProcessing, useDefaultText){
+               
+               chunk.selection = chunk.selection.replace(/^(\n*)([^\r]+?)(\n*)$/,
+                       function(totalMatch, newlinesBefore, text, newlinesAfter){
+                               chunk.before += newlinesBefore;
+                               chunk.after = newlinesAfter + chunk.after;
+                               return text;
+                       });
+                       
+               chunk.before = chunk.before.replace(/(>[ \t]*)$/,
+                       function(totalMatch, blankLine){
+                               chunk.selection = blankLine + chunk.selection;
+                               return "";
+                       });
+               
+               var defaultText = useDefaultText ? "Blockquote" : "";
+               chunk.selection = chunk.selection.replace(/^(\s|>)+$/ ,"");
+               chunk.selection = chunk.selection || defaultText;
+               
+               if(chunk.before){
+                       chunk.before = chunk.before.replace(/\n?$/,"\n");
+               }
+               if(chunk.after){
+                       chunk.after = chunk.after.replace(/^\n?/,"\n");
+               }
+               
+               chunk.before = chunk.before.replace(/(((\n|^)(\n[ \t]*)*>(.+\n)*.*)+(\n[ \t]*)*$)/,
+                       function(totalMatch){
+                               chunk.startTag = totalMatch;
+                               return "";
+                       });
+                       
+               chunk.after = chunk.after.replace(/^(((\n|^)(\n[ \t]*)*>(.+\n)*.*)+(\n[ \t]*)*)/,
+                       function(totalMatch){
+                               chunk.endTag = totalMatch;
+                               return "";
+                       });
+               
+               var replaceBlanksInTags = function(useBracket){
+                       
+                       var replacement = useBracket ? "> " : "";
+                       
+                       if(chunk.startTag){
+                               chunk.startTag = chunk.startTag.replace(/\n((>|\s)*)\n$/,
+                                       function(totalMatch, markdown){
+                                               return "\n" + markdown.replace(/^[ ]{0,3}>?[ \t]*$/gm, replacement) + "\n";
+                                       });
+                       }
+                       if(chunk.endTag){
+                               chunk.endTag = chunk.endTag.replace(/^\n((>|\s)*)\n/,
+                                       function(totalMatch, markdown){
+                                               return "\n" + markdown.replace(/^[ ]{0,3}>?[ \t]*$/gm, replacement) + "\n";
+                                       });
+                       }
+               };
+               
+               if(/^(?![ ]{0,3}>)/m.test(chunk.selection)){
+                       command.wrap(chunk, wmd.wmd_env.lineLength - 2);
+                       chunk.selection = chunk.selection.replace(/^/gm, "> ");
+                       replaceBlanksInTags(true);
+                       chunk.addBlankLines();
+               }
+               else{
+                       chunk.selection = chunk.selection.replace(/^[ ]{0,3}> ?/gm, "");
+                       command.unwrap(chunk);
+                       replaceBlanksInTags(false);
+                       
+                       if(!/^(\n|^)[ ]{0,3}>/.test(chunk.selection) && chunk.startTag){
+                               chunk.startTag = chunk.startTag.replace(/\n{0,2}$/, "\n\n");
+                       }
+                       
+                       if(!/(\n|^)[ ]{0,3}>.*$/.test(chunk.selection) && chunk.endTag){
+                               chunk.endTag=chunk.endTag.replace(/^\n{0,2}/, "\n\n");
+                       }
+               }
+               
+               if(!/\n/.test(chunk.selection)){
+                       chunk.selection = chunk.selection.replace(/^(> *)/,
+                       function(wholeMatch, blanks){
+                               chunk.startTag += blanks;
+                               return "";
+                       });
+               }
+       };
+
+       command.doCode = function(chunk, postProcessing, useDefaultText){
+               
+               var hasTextBefore = /\S[ ]*$/.test(chunk.before);
+               var hasTextAfter = /^[ ]*\S/.test(chunk.after);
+               
+               // Use 'four space' markdown if the selection is on its own
+               // line or is multiline.
+               if((!hasTextAfter && !hasTextBefore) || /\n/.test(chunk.selection)){
+                       
+                       chunk.before = chunk.before.replace(/[ ]{4}$/,
+                               function(totalMatch){
+                                       chunk.selection = totalMatch + chunk.selection;
+                                       return "";
+                               });
+                               
+                       var nLinesBefore = 1;
+                       var nLinesAfter = 1;
+                       
+                       
+                       if(/\n(\t|[ ]{4,}).*\n$/.test(chunk.before) || chunk.after === ""){
+                               nLinesBefore = 0; 
+                       }
+                       if(/^\n(\t|[ ]{4,})/.test(chunk.after)){
+                               nLinesAfter = 0; // This needs to happen on line 1
+                       }
+                       
+                       chunk.addBlankLines(nLinesBefore, nLinesAfter);
+                       
+                       if(!chunk.selection){
+                               chunk.startTag = "    ";
+                               chunk.selection = useDefaultText ? "enter code here" : "";
+                       }
+                       else {
+                               if(/^[ ]{0,3}\S/m.test(chunk.selection)){
+                                       chunk.selection = chunk.selection.replace(/^/gm, "    ");
+                               }
+                               else{
+                                       chunk.selection = chunk.selection.replace(/^[ ]{4}/gm, "");
+                               }
+                       }
+               }
+               else{
+                       // Use backticks (`) to delimit the code block.
+                       
+                       chunk.trimWhitespace();
+                       chunk.findTags(/`/, /`/);
+                       
+                       if(!chunk.startTag && !chunk.endTag){
+                               chunk.startTag = chunk.endTag="`";
+                               if(!chunk.selection){
+                                       chunk.selection = useDefaultText ? "enter code here" : "";
+                               }
+                       }
+                       else if(chunk.endTag && !chunk.startTag){
+                               chunk.before += chunk.endTag;
+                               chunk.endTag = "";
+                       }
+                       else{
+                               chunk.startTag = chunk.endTag="";
+                       }
+               }
+       };
+       
+       command.doList = function(chunk, postProcessing, isNumberedList, useDefaultText){
+                               
+               // These are identical except at the very beginning and end.
+               // Should probably use the regex extension function to make this clearer.
+               var previousItemsRegex = /(\n|^)(([ ]{0,3}([*+-]|\d+[.])[ \t]+.*)(\n.+|\n{2,}([*+-].*|\d+[.])[ \t]+.*|\n{2,}[ \t]+\S.*)*)\n*$/;
+               var nextItemsRegex = /^\n*(([ ]{0,3}([*+-]|\d+[.])[ \t]+.*)(\n.+|\n{2,}([*+-].*|\d+[.])[ \t]+.*|\n{2,}[ \t]+\S.*)*)\n*/;
+               
+               // The default bullet is a dash but others are possible.
+               // This has nothing to do with the particular HTML bullet,
+               // it's just a markdown bullet.
+               var bullet = "-";
+               
+               // The number in a numbered list.
+               var num = 1;
+               
+               // Get the item prefix - e.g. " 1. " for a numbered list, " - " for a bulleted list.
+               var getItemPrefix = function(){
+                       var prefix;
+                       if(isNumberedList){
+                               prefix = " " + num + ". ";
+                               num++;
+                       }
+                       else{
+                               prefix = " " + bullet + " ";
+                       }
+                       return prefix;
+               };
+               
+               // Fixes the prefixes of the other list items.
+               var getPrefixedItem = function(itemText){
+               
+                       // The numbering flag is unset when called by autoindent.
+                       if(isNumberedList === undefined){
+                               isNumberedList = /^\s*\d/.test(itemText);
+                       }
+                       
+                       // Renumber/bullet the list element.
+                       itemText = itemText.replace(/^[ ]{0,3}([*+-]|\d+[.])\s/gm,
+                               function( _ ){
+                                       return getItemPrefix();
+                               });
+                               
+                       return itemText;
+               };
+               
+               chunk.findTags(/(\n|^)*[ ]{0,3}([*+-]|\d+[.])\s+/, null);
+               
+               if(chunk.before && !/\n$/.test(chunk.before) && !/^\n/.test(chunk.startTag)){
+                       chunk.before += chunk.startTag;
+                       chunk.startTag = "";
+               }
+               
+               if(chunk.startTag){
+                       
+                       var hasDigits = /\d+[.]/.test(chunk.startTag);
+                       chunk.startTag = "";
+                       chunk.selection = chunk.selection.replace(/\n[ ]{4}/g, "\n");
+                       command.unwrap(chunk);
+                       chunk.addBlankLines();
+                       
+                       if(hasDigits){
+                               // Have to renumber the bullet points if this is a numbered list.
+                               chunk.after = chunk.after.replace(nextItemsRegex, getPrefixedItem);
+                       }
+                       if(isNumberedList == hasDigits){
+                               return;
+                       }
+               }
+               
+               var nLinesBefore = 1;
+               
+               chunk.before = chunk.before.replace(previousItemsRegex,
+                       function(itemText){
+                               if(/^\s*([*+-])/.test(itemText)){
+                                       bullet = re.$1;
+                               }
+                               nLinesBefore = /[^\n]\n\n[^\n]/.test(itemText) ? 1 : 0;
+                               return getPrefixedItem(itemText);
+                       });
+                       
+               if(!chunk.selection){
+                       chunk.selection = useDefaultText ? "List item" : " ";
+               }
+               
+               var prefix = getItemPrefix();
+               
+               var nLinesAfter = 1;
+               
+               chunk.after = chunk.after.replace(nextItemsRegex,
+                       function(itemText){
+                               nLinesAfter = /[^\n]\n\n[^\n]/.test(itemText) ? 1 : 0;
+                               return getPrefixedItem(itemText);
+                       });
+                       
+               chunk.trimWhitespace(true);
+               chunk.addBlankLines(nLinesBefore, nLinesAfter, true);
+               chunk.startTag = prefix;
+               var spaces = prefix.replace(/./g, " ");
+               command.wrap(chunk, wmd.wmd_env.lineLength - spaces.length);
+               chunk.selection = chunk.selection.replace(/\n/g, "\n" + spaces);
+               
+       };
+       
+       command.doHeading = function(chunk, postProcessing, useDefaultText){
+               
+               // Remove leading/trailing whitespace and reduce internal spaces to single spaces.
+               chunk.selection = chunk.selection.replace(/\s+/g, " ");
+               chunk.selection = chunk.selection.replace(/(^\s+|\s+$)/g, "");
+               
+               // If we clicked the button with no selected text, we just
+               // make a level 2 hash header around some default text.
+               if(!chunk.selection){
+                       chunk.startTag = "## ";
+                       chunk.selection = "Heading";
+                       chunk.endTag = " ##";
+                       return;
+               }
+               
+               var headerLevel = 0;            // The existing header level of the selected text.
+               
+               // Remove any existing hash heading markdown and save the header level.
+               chunk.findTags(/#+[ ]*/, /[ ]*#+/);
+               if(/#+/.test(chunk.startTag)){
+                       headerLevel = re.lastMatch.length;
+               }
+               chunk.startTag = chunk.endTag = "";
+               
+               // Try to get the current header level by looking for - and = in the line
+               // below the selection.
+               chunk.findTags(null, /\s?(-+|=+)/);
+               if(/=+/.test(chunk.endTag)){
+                       headerLevel = 1;
+               }
+               if(/-+/.test(chunk.endTag)){
+                       headerLevel = 2;
+               }
+               
+               // Skip to the next line so we can create the header markdown.
+               chunk.startTag = chunk.endTag = "";
+               chunk.addBlankLines(1, 1);
+
+               // We make a level 2 header if there is no current header.
+               // If there is a header level, we substract one from the header level.
+               // If it's already a level 1 header, it's removed.
+               var headerLevelToCreate = headerLevel == 0 ? 2 : headerLevel - 1;
+               
+               if(headerLevelToCreate > 0){
+                       
+                       // The button only creates level 1 and 2 underline headers.
+                       // Why not have it iterate over hash header levels?  Wouldn't that be easier and cleaner?
+                       var headerChar = headerLevelToCreate >= 2 ? "-" : "=";
+                       var len = chunk.selection.length;
+                       if(len > wmd.wmd_env.lineLength){
+                               len = wmd.wmd_env.lineLength;
+                       }
+                       chunk.endTag = "\n";
+                       while(len--){
+                               chunk.endTag += headerChar;
+                       }
+               }
+       };      
+       
+       command.doHorizontalRule = function(chunk, postProcessing, useDefaultText){
+               chunk.startTag = "----------\n";
+               chunk.selection = "";
+               chunk.addBlankLines(2, 1, true);
+       }
+};
+
+
+Attacklab.wmd_env = {};
+Attacklab.account_options = {};
+Attacklab.wmd_defaults = {version:1, output:"Markdown", lineLength:40, delayLoad:false};
+
+if(!Attacklab.wmd)
+{
+       Attacklab.wmd = function()
+       {
+               Attacklab.loadEnv = function()
+               {
+                       var mergeEnv = function(env)
+                       {
+                               if(!env)
+                               {
+                                       return;
+                               }
+                       
+                               for(var key in env)
+                               {
+                                       Attacklab.wmd_env[key] = env[key];
+                               }
+                       };
+                       
+                       mergeEnv(Attacklab.wmd_defaults);
+                       mergeEnv(Attacklab.account_options);
+                       mergeEnv(top["wmd_options"]);
+                       Attacklab.full = true;
+                       
+                       var defaultButtons = "bold italic link blockquote code image ol ul heading hr";
+                       Attacklab.wmd_env.buttons = Attacklab.wmd_env.buttons || defaultButtons;
+               };
+               Attacklab.loadEnv();
+
+       };
+       
+       Attacklab.wmd();
+       Attacklab.wmdBase();
+       Attacklab.Util.startEditor();
+};
+
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/js/yuicompressor-2.4.2.jar b/forum/modules/template_loader.py/forum/skins/default/media/js/yuicompressor-2.4.2.jar
new file mode 100644 (file)
index 0000000..c29470b
Binary files /dev/null and b/forum/modules/template_loader.py/forum/skins/default/media/js/yuicompressor-2.4.2.jar differ
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/style/admin.css b/forum/modules/template_loader.py/forum/skins/default/media/style/admin.css
new file mode 100644 (file)
index 0000000..51bf919
--- /dev/null
@@ -0,0 +1,54 @@
+#admin_form {
+    border-spacing: 10px;
+}
+
+#admin_form input[type="text"], #admin_form input[type="submit"], #admin_form textarea, .string_list_widget_button {
+    line-height: 22px;
+    font-size: 140%;
+    font-family: sans-serif;
+    border: 1px solid #999;
+    color: black;
+}
+
+#admin_form input[type="text"], #admin_form input[type="submit"], .string_list_widget_button {
+    height: 28px;
+}
+
+#admin_form input[type="text"], #admin_form textarea {
+    width: 550px;    
+}
+
+#admin_form th {
+    text-align: left;
+    vertical-align: top;
+}
+
+#admin_form td {
+    color: gray;
+}
+
+#admin_page_description {
+    color: gray;
+    padding-bottom: 20px;
+}
+
+.string_list_widget input[type=text] {
+    width: 520px;
+}
+
+.string_list_widget_button {
+    width: 28px;
+    font-size: 20px;
+    font-weight: bold;
+}
+
+.string_list_widget_button.add {
+    position: relative;
+    left: 554px;
+}
+
+table caption {
+    font-size: 120%;
+       padding: 3px 0;
+    text-align: left;
+}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/style/auth.css b/forum/modules/template_loader.py/forum/skins/default/media/style/auth.css
new file mode 100644 (file)
index 0000000..0734ce0
--- /dev/null
@@ -0,0 +1,84 @@
+#bigicon_providers, #smallicon_providers {
+    display: block;
+    padding: 0px;
+    width:600px;
+    margin:0px 0px 5px 0px;
+    clear:both;
+}
+
+.provider_logo {
+    display: block;
+    border: 1px solid #DDD;
+    text-align: center;
+}
+
+.provider_logo.big {
+    display: block;
+    border:1px solid #DDDDDD;
+    float:left;
+    height:60px;
+    margin:3px;
+    width:110px;
+}
+
+.provider_logo.big .inner {
+    display:block;
+    margin: 0px auto;
+    margin-top: 18px;
+}
+
+.provider_logo.small {
+    border:1px solid #DDDDDD;
+    float:left;
+    height:30px;
+    margin:3px;
+    width:30px;
+}
+
+.provider_logo.small .inner {
+    display:block;
+    margin: 0px auto;
+    margin-top: 6px;
+}
+
+.provider_logo.selected {
+    outline: 2px solid #FFF8C6;
+}
+
+.provider_logo .provider_url {
+    display: none;
+}
+
+.signin_form {
+    clear:both;
+}
+
+.signin_form fieldset {
+    padding: 10px;
+}
+
+.signin_form input[type="text"], .signin_form input[type="password"], .signin_form input[type="submit"] {
+    height: 28px;
+    line-height: 22px;
+    font-size: 140%;
+    border: 1px solid #999;
+    padding-left:5px;
+    margin-right:5px;
+}
+
+.signin_form input[type="text"], .signin_form input[type="password"] {
+    padding-top:4px;  /* balance of alignment between firefox/safari and IE */
+}
+
+.signin_form .icon_input  {
+    padding-left: 20px;
+}
+
+.signin_form #openid_identifier {
+    padding-left: 18px;
+}
+
+.or_label {
+    margin-top: 20px;
+    margin-bottom: 10px;
+}
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/style/default.css b/forum/modules/template_loader.py/forum/skins/default/media/style/default.css
new file mode 100644 (file)
index 0000000..c8b41f2
--- /dev/null
@@ -0,0 +1,1754 @@
+/*
+Document   : default
+Created on : Dec 9, 2008, 8:48:40 PM
+Author     : Mike
+Description:
+Style sheet for cnprog.com
+All rights reserved. 2008 CNPROG.COM
+*/
+
+@import url(media/style/jquery.autocomplete.css);
+@import url(media/style/openid.css);
+@import url(media/style/prettify.css);
+
+html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, form, label, table, caption, tbody, tfoot, thead, tr, th, td
+{
+       margin: 0;
+       padding: 0;
+       border: 0;
+       font-size: 100%;
+       vertical-align: baseline;
+       background: transparent;
+}
+body{
+    font-family: "segoe ui",Helvetica,"Microsoft YaHei",ËÎÌå,Tahoma,Verdana,MingLiu,PMingLiu,Arial,sans-serif;
+    font-size: 80%;
+
+    margin:0;
+    padding:0;
+    text-align:center;
+    line-height: 1;
+}
+blockquote, q
+{
+       quotes: none;
+}
+blockquote:before, blockquote:after, q:before, q:after
+{
+       content: '';
+       content: none;
+}
+table
+{
+       border-collapse: collapse;
+       border-spacing: 0;
+}
+
+input, select, button, textarea
+{
+       border: 1px solid #999;
+       font-size:100%;
+    font-family:"segoe ui",Helvetica,"Microsoft YaHei",ËÎÌå,Tahoma,Verdana,MingLiu,PMingLiu,Arial,sans-serif;
+}
+
+input
+{
+    /*
+       margin: 5px 0px 5px 0px;*/
+       padding:3px;
+
+}
+
+pre
+{
+       font-family: Consolas, Monaco, Liberation Mono, Lucida Console, Monospace;
+    font-size:100%;
+       margin-bottom: 10px;
+       overflow: auto;
+       width: 580px;
+       background-color: #F5F5F5;
+    padding-left:5px;
+    padding-top:5px;
+       padding-bottom: 20px !ie7;
+}
+
+code{
+    font-family: Consolas, Monaco, Liberation Mono, Lucida Console, Monospace;
+    font-size:100%;
+
+}
+
+blockquote
+{
+       margin-bottom: 10px;
+       margin-right: 15px;
+       padding: 10px 0px 1px 10px;
+       background-color: #F5F5F5;
+}
+
+b, strong
+{
+       font-weight: bold;
+}
+
+i, em
+{
+       font-style: italic;
+}
+
+ul
+{
+       list-style: disc;
+       margin-left: 30px;
+       margin-bottom: 1em;
+}
+
+p
+{
+       clear: both;
+       margin-bottom: 1em;
+}
+
+ol
+{
+       list-style: decimal;
+       margin-left: 30px;
+       margin-bottom: 1em;
+}
+
+a {color:#07c;text-decoration: none;}
+a:visited{color:#3E6D8E;text-decoration: none;}
+a:hover{text-decoration: underline;}
+a:active{text-decoration: none;}
+
+h1 {
+    font-family:Trebuchet MS,Helvetica,sans-serif;
+    font-size: 160%;
+}
+h2 {
+    font-family:Trebuchet MS,Helvetica,sans-serif;
+    font-size:140%;
+    font-weight:bold;
+    margin-bottom:7px;
+}
+h3 {display:block;font-size:120%;font-family:Trebuchet MS,"segoe ui",Helvetica,"Microsoft YaHei",ËÎÌå,Tahoma,Verdana,MingLiu,PMingLiu,Arial,sans-serif;font-weight:bold;}
+h3 a:visited{
+   color:#86B0E1;
+}
+h4 {display:block;font-size:90%; font-family:Verdana;color:#ccc;}
+
+#top{
+    width:100%;
+    border-bottom:solid 3px #ccc;
+    background-color:#eee;
+    margin:0px;
+}
+
+#container{
+    margin: 0px auto;
+    width:950px;
+    display:block;
+    text-align: left;
+}
+
+#header{
+    width:100%;
+    padding:3px 0 10px 0;
+}
+
+#header-links{
+
+}
+
+#header-links a{
+    color:darkred;
+    font-weight:400;
+    font-size:100%;
+    /*letter-spacing:1px;*/
+
+}
+
+#header-links a:hover{
+    text-decoration:none;
+}
+
+
+#content{
+    margin-top:5px;
+}
+
+#main{
+    float:left;
+    width:670px;
+}
+
+#container{
+    width:950px;
+}
+
+#main-bar{
+    border-bottom: 1px solid #666;
+       height: 34px;
+       width: 100%;
+       clear:both;
+    margin-bottom:5px;
+}
+
+#main-bar h3{
+    float: left;
+       font-size: 140%;
+    font-weight:700;
+    /*letter-spacing:3px;*/
+       margin-top:8px;
+    padding:5px 0 0 3px ;
+    height:20px;
+    width:200px;
+    color:#333;
+}
+
+#question-title{
+    float:left;
+    border-bottom: 1px solid #666;
+    width: 98%;
+    clear:both;
+    padding:13px 0px 5px 0;
+    margin-bottom:5px;
+
+}
+
+#question-title h3{
+    font-size: 130%;
+    font-weight:bold;
+    line-height:25px;
+}
+
+#question-title a{
+    color:#333;
+}
+
+#main-body{
+    float:left;
+    width:100%;
+}
+
+#main-bar .golden{
+    background:url(../../images/bg_title_golden.gif) no-repeat;
+}
+
+#main-bar .pink{
+    background:url(../../images/bg_title_red.gif) no-repeat;
+}
+
+#main-bar .orange{
+    background:url(../../images/bg_title_orange.gif) no-repeat;
+}
+
+#main-bar .green{
+    background:url(../../images/bg_title_green.gif) no-repeat;
+}
+
+#tab{
+    float:right;
+    position:relative;
+    display:block;
+    font-weight:bold;
+}
+
+#tab a
+{
+       background: #eee;
+       border: 1px solid #eee;
+       color: #777;
+       display: block;
+       float: left;
+       font-size: 90%;
+       height: 24px;
+       line-height: 22px;
+       margin: 8px 4px 0 0;
+       padding: 0 11px 0 11px;
+       text-decoration: none;
+}
+
+#tab a:hover
+{
+       background: #fff;
+       border: 1px solid #777;
+       border-bottom-color: #fff;
+       line-height: 20px;
+       margin-top: 9px;
+}
+
+#tab a.youarehere
+{
+       background: #fff;
+    color:#333;
+       border: 1px solid #777;
+       border-bottom-color: #fff;
+       font-size: 100%;
+       height: 30px;
+       line-height: 28px;
+       margin-top: 3px;
+       padding: 0px 11px 0px 11px;
+}
+
+#sidebar{
+    float:right;
+    width:260px;
+}
+
+#footer{
+    background:#777777 none repeat scroll 0 0;
+    border-top:7px solid #000000;
+    clear:both;
+    margin-top:30px;
+    overflow:hidden;
+    padding:15px;
+    text-align:center;
+}
+
+#footer a
+{
+       color: White;
+}
+
+#askform{
+    padding:5px;
+    line-height:20px;
+}
+#askform .title-desc{
+    color:#999;
+    font-size:90%;
+}
+
+#askform #description{
+    padding:20px 0 20px 0;
+}
+
+#askform .submit{
+    padding:5px 10px 5px 10px;
+    font-size:120%;
+    font-weight:bold;
+    width:120px;
+    /*letter-spacing:1px;*/
+    background-color:#D4D0C8;
+}
+.notify
+{
+       position: fixed;
+       top: 0px;
+       left: 0px;
+       width: 100%;
+       z-index: 100;
+       padding: 7px 0 5px 0;
+       text-align: center;
+       font-size: 130%;
+       font-weight: Bold;
+       color: #444;
+       background-color: #F4A83D;
+}
+
+.notify span
+{
+       float: left;
+       width: 95%;
+       text-align: center;
+}
+
+.close-notify
+{
+       float: right;
+       margin-right: 20px;
+       color: #735005;
+       text-decoration: none;
+       background-color: #FAD163;
+       border: 2px #735005 solid;
+       padding-left: 3px;
+       padding-right: 3px;
+    cursor:pointer;
+}
+.small{
+    font-size:90%;
+    color:#777;
+}
+.big{
+    font-size:120%;
+    font-weight:600;
+
+}
+
+.paragraph{
+    line-height:20px;
+    margin-bottom:10px;
+}
+
+.paragraph-extra{
+    line-height:30px;
+    margin-bottom:10px;
+}
+
+.darkred{
+    color:darkred;
+}
+
+.yellowbg{
+    background-color:yellow;
+}
+
+.header-table{
+    width:100%;
+    /*solve template header space problem*/
+    margin-top:-12px;
+}
+
+.header-table a{
+    font-weight:bold;
+}
+
+.link-separator{
+    color:#ccc;
+    padding:3px;
+}
+
+.action-link-separator{
+    color:#ccc;
+}
+
+.nav
+{
+       font-size: 120%;
+}
+
+.nav ul
+{
+       margin: 0;
+}
+
+.nav li
+{
+       background: #777;
+       display: block;
+       float: left;
+    margin-right: 7px;
+}
+
+.nav li.youarehere
+{
+       background: #f90;
+}
+
+.nav a
+{
+       color: #fff;
+       display: block;
+       font-weight: bold;
+       padding: 6px 15px 6px 15px;
+       text-decoration: none;
+}
+
+.nav li.youarehere a
+{
+       color: white;
+}
+
+.nav li:hover
+{
+       background-color:#ff9900;
+}
+
+.header-notification{
+    font-size:85%;
+    color:red;
+}
+
+.highlight-box{
+    /*letter-spacing:1px;*/
+    color:#735005;
+}
+
+.highlight-box p{
+    margin:5px 0 0px 0;
+}
+
+.highlight-box a{
+    color:#735005;
+    font-size:90%;
+    font-weight:bold;
+}
+
+.yellow-box{
+    background-color:#FFFFCC;
+    border:1px dotted #D8D2A9;
+    margin-bottom:20px;
+    line-height:20px;
+    padding:10px 10px 5px;
+
+}
+
+.yellow-box ul{
+    margin-left:0px;
+}
+
+.yellow-box h3{
+    font-size:120%;
+    padding-bottom:5px;
+    margin-bottom:10px;
+    border-bottom:1px dotted #D8D2A9;
+}
+
+.gray-box{
+    background-color:#eee;
+    border:1px dotted #D8D2A9;
+    margin-bottom:20px;
+    line-height:20px;
+    padding:10px 10px 5px;
+    overflow:hidden;
+}
+
+.gray-box ul{
+    margin-left:0px;
+}
+
+.gray-box h3{
+    font-size:120%;
+    padding-bottom:5px;
+    margin-bottom:10px;
+    border-bottom:1px dotted #D8D2A9;
+}
+
+.question-item{
+    width:100%;
+    float:left;
+    margin:5px 0 10px 0;
+    border-bottom:1px dotted #D8D2A9;
+}
+
+.boxes{
+    float:left;
+    text-align:center;
+    color:#666;
+}
+
+.boxes-cell{
+    padding-right:5px;
+    vertical-align:top;
+}
+
+.questions-summary-container{
+    float:left;
+    width:580px;
+
+}
+.questions-boxes-container{
+    float:left;
+}
+.questions-boxes{
+    float:left;
+    width: 70px;
+    text-align:center;
+    color:#666;
+
+}
+.questions-vote-number{
+    font-size:200%;
+    font-weight:bold;
+    font-family:Arial;
+}
+.questions-answer-number{
+    font-size:140%;
+    font-weight:bold;
+    font-family:Arial;
+}
+.questions-answerbox{
+    padding:5px;
+}
+
+.questions-votebox{
+    padding:5px;
+}
+.questions-viewbox{
+    padding:5px;
+}
+.qustions-summary{
+    line-height:20px;
+    margin-bottom:5px;
+}
+.question-body{
+    min-height:100px;
+}
+.question-body IMG{
+    max-width:600px;
+}
+.questions-mark{
+    float:right;
+    text-align:left;
+    font-size:90%;
+
+    line-height:20px;
+    width:160px;
+}
+
+.questions-boxicon{
+    width:15px;
+    vertical-align:top;
+}
+.questions-count{
+    font-family:arial;
+    font-size:350%;
+    font-weight:bolder;
+    margin:15px 0 15px 0;
+    color:#777;
+}
+#questions-answerbox-cell{
+    padding:5px;
+
+}
+
+.vote{
+    background-color:#eee;
+}
+
+.box-number{
+    font-size:160%;
+    font-weight:bold;
+    font-family:Arial;
+}
+
+.box-unit{
+    padding:3px;
+    font-size:90%;
+}
+
+.answer{
+    border-bottom:1px dotted #666666;
+    padding-bottom:20px;
+    padding-top:20px;
+    width: 100%;
+    margin-bottom:10px;
+}
+.answer-body{
+    min-height:80px;
+}
+
+.answer-body IMG{
+    max-width:600px;
+}
+
+.accepted-answer{
+    background-color:#E2FCE2;
+    border-bottom-color:#9BD59B;
+}
+
+.accepted-answer .comments-link{
+    background-color:#D9F5D9;
+}
+
+.accepted-answer .comments-container{
+    background-color:#D9F5D9;
+}
+
+.answered
+{
+       background: #75845C;
+       color: white;
+}
+
+.answered-accepted
+{
+       background: #75845C;
+       color: #E1E818;
+}
+
+.answered-by-owner
+{
+       background: #E0EAF1;
+}
+
+.answered-by-owner .comments-link
+{
+    background-color:#D6E4EE;
+}
+
+.answered-by-owner .comments-container
+{
+    background-color:#D6E4EE;
+}
+
+.answered-accepted strong
+{
+       color: #E1E818;
+}
+
+.unanswered
+{
+       background: #9A4444;
+       color: white;
+}
+
+.view{
+
+}
+
+.subtitle{
+    padding:15px 0 10px 0;
+}
+
+.qustion-title{
+    font-size:100%;
+    padding:0px;
+    line-height:20px;
+    margin-bottom:5px;
+}
+
+.question-tag{
+    float:left;
+    padding-bottom:3px;
+    width:250px;
+}
+
+.post-tag
+{
+       color: #3E6D8E;
+       background-color: #E0EAF1;
+       border-bottom: 1px solid #3E6D8E;
+       border-right: 1px solid #7F9FB6;
+       margin: 2px 3px 2px 0;
+       padding: 2px 4px 2px 4px;
+       text-decoration: none;
+    height:20px;
+    font-family:Microsoft Yahei,ËÎÌå,Tahoma;
+       font-size: 90%;
+       line-height: 2.2;
+       white-space:nowrap;
+    vertical-align:baseline;
+}
+
+.post-tag:hover
+{
+       background-color: #3E6D8E;
+       color: #E0EAF1;
+       border-bottom: 1px solid #37607D;
+       border-right: 1px solid #37607D;
+       text-decoration: none;
+}
+
+.highlight-tag{
+    background-color: #3E6D8E;
+    color: #fff;
+    font-weight:bold;
+    border-bottom: 1px solid #3E6D8E;
+    border-right: 1px solid #7F9FB6;
+    margin: 2px 6px 2px 0;
+    padding: 3px 4px 3px 4px;
+    text-decoration: none;
+    font-size: 90%;
+}
+
+.question-started{
+    font-size:90%;
+    padding-top:10px;
+    float:right;
+    padding-bottom:3px;
+
+}
+
+.updatedtime{
+    font-weight:bold;
+    color:#999;
+}
+
+.badge
+{
+       color: #fff;
+       background-color: #333;
+       border: 1px solid #333;
+       margin: 0 3px 3px 0;
+       padding: 4px 8px 4px 3px;
+       color: white !important;
+       text-decoration: none;
+       line-height: 1.9;
+}
+
+.badge:hover
+{
+       border: 1px solid #555;
+       background-color: #555;
+       text-decoration: none;
+}
+
+.badge-item{
+    margin-bottom:10px;
+}
+
+.badge1
+{
+       margin-left:3px;
+    padding-right:2px;
+       font-size: 120%;
+       color: #FFCC00;
+}
+
+.badge2
+{
+       margin-left:3px;
+    padding-right:2px;
+       font-size: 120%;
+       color: #C0C0C0;
+}
+
+.badge3
+{
+       margin-left:3px;
+    padding-right:2px;
+       font-size: 120%;
+       color: #CC9966;
+}
+
+.badgecount
+{
+       color: #808185;
+}
+
+.reputation-score{
+    font-family:arial;
+    font-weight: bold;
+       color: #333;
+       font-size: 120%;
+       margin-right:2px;
+}
+
+#recent-tags .post-tag
+{
+       background-color: #eee;
+       border: none;
+       margin: 0;
+       font-size: 100%;
+       color: black !important;
+}
+
+#recent-tags .post-tag:hover
+{
+       background-color: #777;
+       color: White !important;
+       border: none;
+       margin: 0;
+       text-decoration: none;
+}
+
+#related-tags{
+    line-height:30px;
+}
+
+.list-item{
+    list-style:inside square
+
+}
+.list-item li{
+    margin-bottom:5px;
+}
+
+.list-item dt{
+    line-height:20px;
+}
+
+.list-item dd{
+    line-height:20px;
+    margin-bottom:10px;
+}
+
+#editor{
+    font-size:100%;
+    min-height:200px;
+    line-height: 18px;
+    width:595px;
+}
+
+.wmd-preview{
+    margin-top:10px;
+    padding:6px;
+    width:590px;
+    background-color:#F5F5F5;
+    min-height:20px;
+}
+
+/*adjustment for editor preview*/
+.wmd-preview pre{
+    background-color:#E7F1F8;
+
+}
+
+.wmd-preview blockquote
+{
+       background-color: #eee;
+}
+
+.wmd-preview IMG{
+    max-width:600px;
+}
+.preview-toggle{
+    font-size:90%;
+    font-weight:600;
+    margin-bottom:-10px;
+    width:600px;
+    color:#aaa;
+    /*letter-spacing:1px;*/
+
+}
+
+.preview-toggle span:hover{
+    cursor:pointer;
+}
+
+.edit-content-html{
+    border-top:1px dotted #D8D2A9;
+    border-bottom:1px dotted #D8D2A9;
+    margin:5px 0 5px 0;
+}
+
+/* 2 textarea resizer styles */
+div.grippie {
+    background:#EEEEEE url(../../images/grippie.png) no-repeat scroll center 2px;
+    border-color:#DDDDDD;
+    border-style:solid;
+    border-width:0pt 1px 1px;
+    cursor:s-resize;
+    height:9px;
+    overflow:hidden;
+    width:600px;
+}
+.resizable-textarea textarea {
+    display:block;
+    margin-bottom:0pt;
+    width:95%;
+    height: 20%;
+}
+
+.openid-input{
+    background:url(../../images/openid.gif) no-repeat;
+    padding-left:15px;
+    cursor:pointer;
+}
+
+.openid-login-input{
+    background-position:center left;
+    background:url(../../images/openid.gif) no-repeat 0% 50%;
+    padding:5px 5px 5px 15px;
+    cursor:pointer;
+    font-family:Trebuchet MS;
+    font-weight:300;
+    font-size:150%;
+    width:500px;
+}
+
+.openid-login-submit{
+    padding:6px;
+    /*padding:4px;*/
+    cursor:pointer;
+    font-weight:bold;
+    font-size:120%;
+    background-color:#D4D0C8;
+}
+
+.openid-samples{
+
+}
+
+.openid-samples .list, .list li{
+    font-family:Trebuchet MS,"segoe ui",Helvetica,"Microsoft YaHei",ËÎÌå,Tahoma,Verdana,MingLiu,PMingLiu,Arial,sans-serif;
+    list-style:none !important;
+    margin-left:-30px !important;
+    line-height:20px !important;
+}
+
+.darkred{
+    color:darkred;
+}
+
+.gray{
+    color:gray;
+}
+
+.message{
+    padding:5px;
+    font-weight:bold;
+    background-color:#eee;
+    margin:10px 0 10px 0;
+}
+
+.warning{
+    color:red;
+}
+
+.vote-buttons{
+    float:left;
+    text-align:center;
+    border:solid 0px #ccc;
+}
+
+.vote-buttons img{
+    cursor:pointer;
+}
+
+.item-right{
+    float:left;
+}
+
+.vote-number{
+    font-family:Arial;
+    padding:0px 0 3px 0;
+    font-size:220%;
+    font-weight:bold;
+    color:#777;
+}
+.favorite-number{
+    font-size:100%;
+    font-family:Arial;
+    margin-top:-8px;
+    font-weight:bold;
+    color:#808185
+}
+
+.my-favorite-number{
+    color:#D4A849;
+}
+
+.tag-number{
+    font-size:120%;
+    font-family:Arial;
+    font-weight:bold;
+}
+
+#question-tags{
+    margin:5px 0 5px 0;
+}
+
+.question-tag-extra{
+    float:left;
+    padding-bottom:3px;
+    width:100%;
+}
+
+.question-mark{
+    background-color:#E0EAF1;
+    text-align:left;
+    font-size:90%;
+    padding:5px;
+    overflow:hidden;
+}
+
+.question-edit{
+    text-align:left;
+    font-size:90%;
+
+    overflow:hidden;
+}
+
+.question-status{
+    margin-top:10px;
+    padding: 20px;
+    background-color:#eee;
+    text-align:center;
+}
+
+.answer-mark{
+    text-align:left;
+    font-size:90%;
+    padding:5px;
+}
+
+.wiki-category{
+    margin-left:5px;
+    color:#999;
+    font-size:90%;
+}
+
+.offensive-flag a{
+    color:#777;
+    font-size:90%;
+    padding:3px;
+    cursor:pointer;
+}
+
+.offensive-flag a:hover{
+    background-color:#777;
+    text-decoration:none;
+    color:#fff;
+}
+
+.linksopt a{
+    color:#777;
+    font-size:90%;
+    padding:3px;
+    cursor:pointer;
+}
+
+.linksopt a:hover{
+    background-color:#777;
+    text-decoration:none;
+    color:#fff;
+}
+
+.action-link a{
+    color:#777;
+    font-size:90%;
+    padding:3px;
+    cursor:pointer;
+}
+
+.action-link a:hover{
+    background-color:#777;
+    text-decoration:none;
+    color:#fff;
+}
+
+.dot-line{
+    border-bottom:1px dotted #D8D2A9;
+    width:670px; /*IE*/
+    /*
+    width:100% !important;
+    */
+    margin-bottom:20px;
+}
+
+.line{
+    border-bottom:1px solid #777;
+    width:650px; /*IE*/
+    /*
+    width:100% !important;
+    */
+    margin-bottom:20px
+}
+
+.taglist-td{
+    width:190px;
+    line-height:26px;
+}
+
+.list-table{
+    margin-left:15px;
+}
+
+.list-td{
+    width:185px;
+
+}
+
+.submit{
+    cursor:pointer;
+    #padding-bottom:0px;
+    #padding-top:0px
+    background-color:#D4D0C8;
+}
+
+form .error{
+    color:darkred;
+}
+
+form .errorlist li{
+    color: red;
+}
+
+.vote-notification
+{
+       z-index: 1;
+       cursor: pointer;
+       display: none;
+       position: absolute;
+       padding: 15px;
+    color: White;
+       background-color: #AE0000;
+}
+
+.vote-notification a
+{
+    color: White;
+       text-decoration:underline;
+}
+
+.center-container{
+    width:950px;
+}
+
+#revisions{
+    width:950px;
+}
+
+.revision{
+    margin:10px 0 10px 0;
+    width:100%;
+}
+
+.revision .header{
+    background-color:#eee;
+    padding:5px;
+    cursor:pointer;
+}
+
+.revision .author{
+    background-color:#E0EAF1;
+}
+
+.revision .summary{
+    padding: 5px 0 10px 0;
+}
+
+.revision .summary span{
+    /**background-color:yellow;/**/
+    display:inline;
+}
+.revision h1{
+    font-size:130%;
+    font-weight:600;
+    padding:15px 0 15px 0;
+}
+
+.revision-mark{
+    width:200px;
+    text-align:left;
+    font-size:90%;
+    overflow:hidden;
+}
+
+.revision-number{
+    font-size:300%;
+    font-weight:bold;
+    font-family:arial;
+}
+
+.revision .body{
+    padding-left:10px;
+    margin-bottom:50px;
+}
+.revision .answerbody{
+    padding:10px 0 5px 10px;
+}
+
+/* Revision pages */
+del { color: #FF5F5F; }
+del .post-tag{
+color: #FF5F5F;
+};
+ins { background-color: #97ff97;}
+ins .post-tag{
+background-color: #97ff97;
+};
+
+/** PAGINATOR **/
+.paginator {
+    padding:5px 0 10px 0;
+    font:normal .8em arial;
+}
+
+.paginator .prev-na,
+.paginator .next-na {
+       padding:.3em;
+       font:bold .875em arial;
+}
+
+.paginator .prev-na,
+.paginator .next-na {
+       border:1px solid #ccc;
+       background-color:#f9f9f9;
+       color:#aaa;
+       font-weight:normal;
+}
+
+.paginator .prev a, .paginator .prev a:visited,
+.paginator .next a, .paginator .next a:visited {
+       border:1px solid #fff;
+       background-color:#fff;
+       color:#777;
+       padding:.3em;
+       font:bold 100% arial;
+}
+
+.paginator .prev, .paginator .prev-na { margin-right:.5em; }
+.paginator .next, .paginator .next-na { margin-left:.5em; }
+
+.paginator .page a, .paginator .page a:visited, .paginator .curr {
+       padding:.25em;
+       font:normal .875em verdana;
+       border:1px solid #ccc;
+       background-color:#fff;
+       margin:0em .25em;
+       color:#777;
+}
+
+.paginator .curr {
+       background-color:#777;
+       color:#fff;
+       border:1px solid #777;
+       font-weight:bold;
+       font-size:1em;
+}
+
+.paginator .page a:hover,
+.paginator .curr a:hover,
+.paginator .prev a:hover,
+.paginator .next a:hover {
+       color:#fff;
+       background-color:#777;
+       border:1px solid #777;
+    text-decoration:none;
+}
+
+.paginator .text{
+    color:#777;
+       padding:.3em;
+       font:bold 100% arial;
+}
+
+.paginator-container{
+    float:right;
+    padding:10px 0 10px 0;
+}
+
+.paginator-container-left{
+    padding:5px 0 10px 0;
+}
+
+.user-info {
+    clear:both;
+    height:45px;
+}
+
+.user-info .user-action-time {
+    margin-bottom:4px;
+    margin-top:2px;
+}
+
+.user-info .user-details {
+    float:left;
+    margin-left:5px;
+    overflow:hidden;
+    white-space:nowrap;
+    width:138px;
+}
+.user-details {
+    color:#888888;
+    line-height:17px;
+}
+
+table.user-details td {
+    color:Black;
+    padding:4px 0;
+}
+
+.user-info .user-gravatar32 {
+    float:left;
+    width:32px;
+}
+
+#mainbar-full {
+    width:950px;
+}
+
+#subheader {
+    border-bottom:1px solid #666666;
+    clear:both;
+    height:34px;
+    width:100%;
+}
+
+#tabs {
+    float:right;
+    font-weight:bold;
+    position:relative;
+}
+
+.summaryinfo {
+    color:#808185;
+    text-align:center;
+}
+
+.summarycount {
+    font-family:arial;
+    color:#808185;
+    font-size:350%;
+    font-weight:bold;
+    text-align:center;
+}
+.summarysubcount {
+    font-family:arial;
+    color:#808185;
+    font-size:250%;
+    font-weight:bold;
+    text-align:center;
+}
+
+
+#user-about-me {
+    background-color:#EEEEEE;
+    height:200px;
+    line-height:20px;
+    margin:10px;
+    overflow:auto;
+    padding:10px;
+    width:90%;
+}
+
+.favorites-count-off {
+    color:#919191;
+    float:left;
+    margin-top:13px;
+    text-align:center;
+}
+
+.favorites-count {
+    color:#D4A849;
+    float:left;
+    margin-top:13px;
+    text-align:center;
+}
+
+.question-summary {
+    border-bottom:1px dotted #999999;
+    float:left;
+    overflow:hidden;
+    padding:11px 0;
+    width:670px;
+}
+
+.user-stats-table .question-summary {
+    width:800px;
+}
+
+.narrow .stats {
+    background:transparent none repeat scroll 0 0;
+    float:left;
+    height:48px;
+    margin:0 0 0 7px;
+    padding:0;
+    width:auto;
+}
+
+.narrow .votes {
+    background:#EEEEEE none repeat scroll 0 0;
+    float:left;
+    height:38px;
+    margin:0 3px 0 0;
+    padding:5px;
+    width:38px;
+}
+
+.narrow .views {
+    float:left;
+    height:38px;
+    margin:0 7px 0 0;
+    padding:5px 0 5px 4px;
+    width:40px;
+}
+
+.narrow .status {
+    float:left;
+    height:38px;
+    margin:0 3px 0 0;
+    padding:5px;
+    width:48px;
+}
+
+.narrow .vote-count-post {
+    font-size:100%;
+    margin:0;
+}
+
+div.votebox {
+    text-align:center;
+    vertical-align:middle;
+}
+
+div.votebox span {
+    color:#808185;
+    display:block;
+    font-weight:bold;
+}
+.vote-count-post {
+    display:block;
+    font-size:240%;
+}
+
+.answered-accepted {
+    background:#75845C none repeat scroll 0 0;
+    color:#E1E818;
+}
+
+.status {
+    margin-top:-3px;
+    padding:4px 0;
+    text-align:center;
+}
+
+.views {
+    color:#999999;
+    padding-top:4px;
+    text-align:center;
+}
+
+.user-stats-table .summary {
+    width:600px;
+    line-height:22px;
+}
+
+.user-stats-table .summary h3{
+    margin:0px;
+    padding:0px;
+}
+
+div.tags {
+    float:left;
+    line-height:18px;
+}
+
+div.started {
+    color:#999999;
+    float:right;
+    line-height:18px;
+    width:185px;
+}
+
+.narrow div.started {
+    line-height:inherit;
+    padding-top:4px;
+    white-space:nowrap;
+    width:auto;
+}
+
+.relativetime {
+    font-weight:bold;
+    text-decoration:none;
+}
+
+div.started a {
+    font-weight:bold;
+}
+
+div.started .reputation-score {
+    margin-left:1px;
+}
+
+.answer-summary {
+    clear:both;
+    padding:3px;
+}
+
+.answer-votes {
+    background-color:#EEEEEE;
+    color:#555555;
+    float:left;
+    font-size:110%;
+    font-weight:bold;
+    height:15px;
+    padding:4px 4px 5px;
+    text-align:center;
+    text-decoration:none;
+    width:20px;
+}
+
+.answered-accepted {
+    background:#75845C none repeat scroll 0 0;
+    color:#E1E818;
+}
+
+.answer-link {
+    color:#555555;
+    float:left;
+    margin-top:5px;
+    padding-left:10px;
+    width:700px;
+}
+
+.answer-link a {
+    font-weight:bold;
+}
+
+.deleted{
+    background:#F4E7E7 none repeat scroll 0 0;
+}
+
+#mainbar-footer {
+    clear:both;
+    width:100%;
+}
+
+#feed-link {
+    float:right;
+    text-align:right;
+}
+
+#feed-link-image {
+    float:left;
+    margin-left:12px;
+    margin-right:5px;
+}
+
+#feed-link-text {
+    float:left;
+}
+
+.revision-comment {
+    background-color:#FFFE9B;
+    color:#333333;
+    line-height:1.4;
+    padding:3px;
+}
+
+.accept-answer-link {
+    color:#508850 !important;
+    font-weight:bold;
+}
+
+.accept-answer-link:hover {
+    background-color:#508850 !important;
+    color:#E1E818 !important;
+    text-decoration:none;
+}
+
+div.comments {
+    line-height:150%;
+    padding:10px 0;
+}
+
+div.post-comments{
+    width:585px;
+    clear:both;
+    float:left;
+}
+
+form.post-comments textarea {
+    height:6em;
+    margin-bottom:4px;
+}
+
+form.post-comments input {
+    margin-left:10px;
+    margin-top:1px;
+    vertical-align:top;
+    width:100px;
+}
+
+span.text-counter {
+    margin-right:20px;
+}
+
+span.form-error {
+    color:#990000;
+    font-size:90%;
+    font-weight:normal;
+    margin-left:5px;
+}
+
+div.comments-container, div.comments-container-accepted, div.comments-container-owner, div.comments-container-deleted {
+    display:none;
+    margin-top:-1px;
+    padding:0 5px 5px;
+}
+
+div.comments-container, a.comments-link {
+    background-color:#EEEEEE;
+}
+
+.post-comments a {
+    color:#888888;
+    padding:0 3px 2px;
+    font-size:90%;
+}
+
+a.comments-link, a.comments-link-accepted, a.comments-link-owner, a.comments-link-deleted {
+    color:black;
+    padding:2px;
+    cursor:pointer;
+}
+
+.post-comments a:hover {
+    background-color:#777777;
+    color:white;
+    text-decoration:none;
+}
+
+a.comment-user, a.comment-user:hover {
+    background-color:inherit;
+    color:#0077CC;
+    padding:0;
+}
+
+a.comment-user:hover {
+    text-decoration:underline;
+}
+
+.user-action{
+
+}
+.user-action-1{
+    font-weight:bold;
+    color:#333;
+}
+.user-action-2{
+    font-weight:bold;
+    color:#75845C;
+}
+.user-action-3{
+    color:#333;
+}
+.user-action-4{
+    color:#333;
+}
+.user-action-5{
+    color:darkred;
+}
+.user-action-6{
+    color:darkred;
+}
+.user-action-7{
+    color:#333;
+}
+.user-action-8{
+    padding:3px;
+    font-weight:bold;
+    background-color:#75845C;
+    color:#E1E818;
+}
+
+.revision-summary{
+    /**background-color:#FFFE9B;/**/
+    padding:2px;
+}
+.question-title-link a{
+    font-weight:bold;
+    color:#0077CC;
+}
+.answer-title-link a{
+    color:#333;
+}
+
+.post-type-1 a {
+    font-weight:bold;
+    color:#0077CC;
+}
+.post-type-3 a {
+    font-weight:bold;
+    color:#0077CC;
+}
+.post-type-5 a {
+    font-weight:bold;
+    color:#0077CC;
+}
+.post-type-2 a{
+    color:#333;
+}
+.post-type-4 a{
+    color:#333;
+}
+.post-type-6 a{
+    color:#333;
+}
+.post-type-8 a{
+    color:#333;
+}
+
+/* openid styles */
+.form-row{line-height:25px;}
+.submit-row{line-height:30px;padding-top:10px;}
+.errors{line-height:20px;color:red;}
+.error{color:red;}
+.error-list li{padding:5px;}
+.login{margin-bottom:10px;}
+.fieldset{border:solid 1px #777;margin-top:10px;padding:10px;}
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/style/djstyle_admin.css b/forum/modules/template_loader.py/forum/skins/default/media/style/djstyle_admin.css
new file mode 100644 (file)
index 0000000..abc479b
--- /dev/null
@@ -0,0 +1,57 @@
+@import "jquery.autocomplete.css";
+
+textarea {
+    width: 100%;
+}
+
+input.longstring {
+    width: 100%;
+}
+
+#admin_form tr th {
+    white-space: nowrap;        
+}
+
+#admin_form tr th a {
+    font-size: 80%;        
+}
+
+#admin_form tr th .sep {
+    font-size: 80%;
+    margin-left: 6px;
+    margin-right: 6px;
+}
+
+#admin_form tr td:first-of-type {
+    width: 100%;
+}
+
+.string-list-input {
+    vertical-align: middle;
+}
+
+.string-list-input input {
+    width: 600px;
+    margin: 0px;
+}
+
+.string_list_widget_button {
+    background:url("../img/admin/nav-bg.gif") repeat-x scroll center bottom #dcdcdc;
+    border-color:#DDDDDD #AAAAAA #AAAAAA #DDDDDD;
+    border-style:solid;
+    border-width:1px;
+    color:black;
+    height: 20px;
+    width: 20px;
+}
+
+.string_list_widget_button.add {
+    position: relative;
+    left: 612px;
+}
+
+.admin_message {
+    background-color: #ffffe0;
+    border: 3px double #b8860b;
+    padding: 4px;
+}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/style/jquery.autocomplete.css b/forum/modules/template_loader.py/forum/skins/default/media/style/jquery.autocomplete.css
new file mode 100644 (file)
index 0000000..b819393
--- /dev/null
@@ -0,0 +1,49 @@
+.ac_results {
+       padding: 0px;
+       border: 1px solid black;
+       background-color: white;
+       overflow: hidden;
+       z-index: 99999;
+    text-align:left;
+}
+
+.ac_results ul {
+       width: 100%;
+       list-style-position: outside;
+       list-style: none;
+       padding: 0;
+       margin: 0;
+}
+
+.ac_results li {
+       margin: 0px;
+       padding: 2px 5px;
+       cursor: default;
+       display: block;
+       /* 
+       if width will be 100% horizontal scrollbar will apear 
+       when scroll mode will be used
+       */
+       /*width: 100%;*/
+       font: menu;
+       font-size: 12px;
+       /* 
+       it is very important, if line-height not setted or setted 
+       in relative units scroll will be broken in firefox
+       */
+       line-height: 16px;
+       overflow: hidden;
+}
+
+.ac_loading {
+       background: white url(../../media/images/indicator.gif) right center no-repeat;
+}
+
+.ac_odd {
+       background-color: #E7F1F8;
+}
+
+.ac_over {
+       background-color: #0A246A;
+       color: white;
+}
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/style/markdown_help.css b/forum/modules/template_loader.py/forum/skins/default/media/style/markdown_help.css
new file mode 100644 (file)
index 0000000..13bc94a
--- /dev/null
@@ -0,0 +1,45 @@
+div.main-wrapper {
+    /*
+    margin: 30px auto;
+    overflow:hidden;
+    position:relative;
+    */
+}
+
+div.section {
+    padding-top:30px;
+}
+
+h2.section-title {
+    padding-top:10px;
+    padding-left:10px;
+    width:100%;
+    background-color:#b6c4e2;
+}
+
+div.section-description {
+    padding-top:20px;
+    padding-bottom:10px;
+}
+
+table.section-example {
+    padding-top:5px;
+    padding-bottom:10px;
+    width:100%;
+}
+
+table.section-example tr {
+}
+
+table.section-example tr td {
+    background-color:#e5ebf8;
+
+    padding:5px 5px 5px 5px;
+    width:50%;
+
+    text-align:left;
+
+    border: 1px solid #ccc;
+    -moz-border-radius:5px;
+    -webkit-border-radius:5px;
+}
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/style/openid.css b/forum/modules/template_loader.py/forum/skins/default/media/style/openid.css
new file mode 100644 (file)
index 0000000..0d201df
--- /dev/null
@@ -0,0 +1,45 @@
+#openid_form {
+       width: 470px;   
+}
+       #openid_form legend {
+               font-weight: bold;
+       }
+#openid_choice {
+       display: none;
+}
+#openid_input_area {
+       clear: both;
+       padding: 10px;
+}
+#openid_btns, #openid_btns br {
+       clear: both;
+}
+       #openid_highlight {
+               padding: 3px;
+               background-color: #FFFCC9;
+               float: left;
+       }
+       .openid_large_btn {
+               width: 100px;
+               height: 60px;
+               border: 1px solid #DDD;
+               margin: 3px;
+               float: left;
+       }
+       .openid_small_btn {
+               width: 24px;
+               height: 24px;
+               border: 1px solid #DDD;
+               margin: 3px;
+               float: left;
+       }       
+       a.openid_large_btn:focus {
+               outline: none;
+       }
+       a.openid_large_btn:focus
+       {
+       -moz-outline-style: none;
+       }
+       .openid_selected {
+               border: 4px solid #DDD;
+       }       
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/style/prettify.css b/forum/modules/template_loader.py/forum/skins/default/media/style/prettify.css
new file mode 100644 (file)
index 0000000..10a3757
--- /dev/null
@@ -0,0 +1,27 @@
+/* Pretty printing styles. Used with prettify.js. */
+
+.str { color: #080; }
+.kwd { color: #008; }
+.com { color: #800; }
+.typ { color: #606; }
+.lit { color: #066; }
+.pun { color: #660; }
+.pln { color: #000; }
+.tag { color: #008; }
+.atn { color: #606; }
+.atv { color: #080; }
+.dec { color: #606; }
+pre.prettyprint { padding: 3px; border: 0px solid #888; }
+
+@media print {
+  .str { color: #060; }
+  .kwd { color: #006; font-weight: bold; }
+  .com { color: #600; font-style: italic; }
+  .typ { color: #404; font-weight: bold; }
+  .lit { color: #044; }
+  .pun { color: #440; }
+  .pln { color: #000; }
+  .tag { color: #006; font-weight: bold; }
+  .atn { color: #404; }
+  .atv { color: #060; }
+}
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/style/style.css b/forum/modules/template_loader.py/forum/skins/default/media/style/style.css
new file mode 100644 (file)
index 0000000..e0b8052
--- /dev/null
@@ -0,0 +1,1828 @@
+@import "jquery.autocomplete.css";
+
+body {
+    /*overflow-y: scroll;
+    height: 100%; */
+    background: none repeat scroll 0 0 #FFFFFF;
+    color: #000000;
+    font-family: sans-serif;
+    font-size: 12px;
+    line-height: 150%;
+    margin: 0;
+    padding: 0;
+}
+
+div {
+    margin: 0 auto;
+    padding: 0;
+}
+
+h1, h2, h3, ul, li, form, img, p {
+    border: medium none;
+    margin: 0;
+    padding: 0;
+}
+
+label {
+    vertical-align: middle;
+}
+
+.login label {
+    display: block;
+}
+
+.login .form-row-vertical {
+    margin-bottom: 8px;
+}
+
+hr {
+    border-color: #CCCCCE -moz-use-text-color -moz-use-text-color;
+    border-right: medium none;
+    border-style: dashed none none;
+    border-width: 1px medium medium;
+}
+
+input, select {
+    font-family: Trebuchet MS, "segoe ui", Helvetica, "Microsoft YaHei", Tahoma, Verdana, MingLiu, PMingLiu, Arial, sans-serif;
+    vertical-align: middle;
+}
+
+p {
+    font-size: 13px;
+    line-height: 140%;
+    margin-bottom: 13px;
+}
+
+a {
+    color: #3060A8;
+    text-decoration: none;
+}
+
+.clear {
+  clear: both;
+  width: 0px;
+  height: 0px;
+}
+
+.badges a {
+    color: #763333;
+    text-decoration: underline;
+}
+
+a:hover {
+    text-decoration: underline;
+}
+
+.tright {
+    text-align: right;
+}
+
+.spacer3 {
+    clear: both;
+    height: 30px;
+    line-height: 30px;
+    visibility: hidden;
+}
+
+h1 {
+    font-size: 160%;
+    padding: 5px 0;
+    line-height: 110%;
+}
+
+h2 {
+    font-size: 140%;
+    padding: 3px 0;
+    line-height: 110%;
+}
+
+h3 {
+    font-size: 120%;
+    padding: 3px 0;
+    line-height: 110%;
+}
+
+ul {
+    list-style: disc outside none;
+    margin-bottom: 1em;
+    margin-left: 20px;
+    padding-left: 0;
+}
+
+ol {
+    list-style: decimal outside none;
+    margin-bottom: 1em;
+    margin-left: 30px;
+    padding-left: 0;
+}
+
+td ul {
+    vertical-align: middle;
+}
+
+li input {
+    margin: 3px 3px 4px;
+}
+
+pre {
+    background-color: #F5F5F5;
+    font-family: Consolas, Monaco, Liberation Mono, Lucida Console, Monospace;
+    font-size: 100%;
+    margin-bottom: 10px;
+    overflow: auto;
+    padding-left: 5px;
+    padding-top: 5px;
+    width: 580px;
+}
+
+code {
+    font-family: Consolas, Monaco, Liberation Mono, Lucida Console, Monospace;
+    font-size: 100%;
+}
+
+blockquote {
+    background-color: #F5F5F5;
+    margin-bottom: 10px;
+    margin-right: 15px;
+    padding: 10px 0 1px 10px;
+    max-width: 650px;
+}
+
+#wrapper, #announcement {
+    margin: auto;
+    padding: 0;
+    width: 990px;
+    background-color: #FFF;
+}
+
+#roof {
+    width: 990px;
+}
+
+#room {
+    background-color: #FFFFFF;
+    border-bottom: 1px solid #777777;
+    padding: 10px 0;
+}
+
+#CALeft {
+    float: left;
+    position: relative;
+    width: 740px;
+}
+
+#CARight {
+    float: right;
+    width: 240px;
+}
+
+#CAFull {
+    float: left;
+    padding: 0 5px;
+    width: 950px;
+}
+
+#ground {
+    background: none repeat scroll 0 0 #BDCCED;
+    border-top: 1px solid #000000;
+    padding-bottom: 0;
+    padding-top: 6px;
+    text-align: center;
+    width: 990px;
+}
+
+#top {
+    float: right;
+    background-color: #FFFFFF;
+    padding: 3px;
+    text-align: right;
+    width: 500px;
+}
+
+#top a {
+    color: #333333;
+    font-size: 12px;
+    height: 35px;
+    margin-left: 20px;
+    text-align: right;
+    text-decoration: underline;
+}
+
+#logo {
+    float: left;
+    padding: 5px 0 0;
+}
+
+#nav {
+    float: right;
+    margin: 35px 0px 0px 0px;
+    width: 750px;
+}
+
+#nav a {
+    background-color: #E5EBF8;
+    border-color: #888888 #888888 -moz-use-text-color;
+    border-style: solid solid none;
+    border-width: 1px 1px medium;
+    color: #333333;
+    display: block;
+    float: left;
+    font-size: 14px;
+    font-weight: 400;
+    height: 25px;
+    line-height: 30px;
+    margin-left: 10px;
+    padding: 0 12px 3px;
+    text-decoration: none;
+}
+
+#nav a:hover {
+    text-decoration: underline;
+}
+
+#nav a.on {
+    background: none repeat scroll 0 0 #356FCB;
+    border: 1px solid #356FCB;
+    color: #FFFFFF;
+    font-weight: 600;
+    height: 24px;
+    line-height: 28px;
+    text-decoration: none;
+}
+
+#nav a#nav_ask {
+    float: right;
+    color: #B02B2C;
+    font-size: 14px;
+    font-weight: bold;
+    text-decoration: none;
+}
+
+#nav a#nav_ask:hover {
+    text-decoration: underline;
+}
+
+#nav a#nav_ask.on {
+   color: #FFFFFF;
+}
+
+#searchBar {
+    text-align: center;
+    background-color: #B6C4E2;
+    border-color: #EEEEEC #A9ACA5 #BABDB6 #EEEEEC;
+    border-style: solid;
+    border-width: 1px;
+    padding: 4px 0 0;
+    width: 988px;
+}
+
+#searchBar .content {
+}
+
+#searchBar .searchInput {
+    border: 0px;
+    padding: 3px;
+    font-size: 13px;
+    height: 18px;
+    width: 400px;
+}
+
+#searchBar .searchBtn {
+    font-size: 14px;
+    height: 26px;
+    width: 80px;
+}
+
+#searchBar .options {
+    color: #333333;
+    font-size: 120%;
+    padding: 3px 0;
+}
+
+#searchBar .options input {
+    margin: 0 3px 0 15px;
+}
+
+#searchBar .options input:hover {
+    cursor: pointer;
+}
+
+#listA {
+    background-color: #FFFFFF;
+    float: left;
+    padding: 0 0;
+    width: 100%;
+}
+
+.thousand {
+    color: orange;
+}
+
+.short-summary {
+    border-top: 1px dotted #CCCCCE;
+    float: left;
+    overflow: hidden;
+    padding: 3px 0px 5px 0;
+    position: relative;
+    width: 740px;
+}
+
+#listA .short-summary:first-of-type {
+    border-top: 0;
+}
+
+.user-stats-table .short-summary {
+    width: 764px;
+}
+
+.short-summary h2 a {
+    color: #2A5594;
+    font-family: "Trebuchet MS", "segoe ui", arial, sans-serif;
+    font-size: 17px;
+}
+
+.short-summary .userinfo {
+    color: #666666;
+    float: right;
+    margin-top: 8px;
+}
+
+.userinfo a, a.userinfo {
+    color: #3060A8;
+}
+
+.short-summary .counts {
+    float: left;
+    margin-right: 0px;
+    margin-top: 4px;
+    padding-right: 2px;
+}
+
+.short-summary .counts .item-count {
+    font-size: 17px;
+    font-weight: bold;
+}
+
+.short-summary .question-summary-wrapper {
+  float: right;
+  width: 565px;
+}
+
+.short-summary .votes, .short-summary .status, .short-summary .views {
+    -moz-border-radius: 5px 5px 5px 5px;
+    border-bottom: 1px solid #CCCCCC;
+    border-right: 1px solid #CCCCCC;
+    float: left;
+    font-size: 11px;
+    height: 42px;
+    margin: 0 6px 0 0px;
+    padding: 8px 2px 0;
+    text-align: center;
+    width: 46px;
+}
+
+.short-summary .votes, .short-summary .views {
+    color: #666666;
+}
+
+.short-summary .favorites {
+    width: 24px;
+    float: left;
+    text-align: center;
+}
+
+#question-table {
+    margin-bottom: 10px;
+}
+
+.questions-count {
+    color: #A40000;
+    font-family: sans-serif;
+    font-size: 24px;
+    font-weight: 600;
+    margin-top: 3px;
+    margin-right: 5px;
+    padding: 0 0 5px 0;
+}
+
+.boxA {
+    background: none repeat scroll 0 0 #888A85;
+    margin-bottom: 8px;
+    padding: 6px;
+}
+
+.boxA h3 {
+    color: #FFFFFF;
+    font-size: 13px;
+    font-weight: 800;
+    margin: 0 0 4px;
+    padding: 0;
+}
+
+.boxA .body {
+    background: none repeat scroll 0 0 #FFFFFF;
+    border: 1px solid #999999;
+    font-size: 13px;
+    padding: 8px;
+}
+
+.boxA .more {
+    font-weight: 800;
+    padding: 2px;
+    text-align: right;
+}
+
+.boxC {
+    background: none repeat scroll 0 0 #E5EBF8;
+    border-color: #EEEEEC #A9ACA5 #BABDB6 #EEEEEC;
+    border-style: solid;
+    border-width: 1px;
+    margin-bottom: 8px;
+    padding: 10px;
+}
+
+.boxC p {
+    margin-bottom: 8px;
+}
+
+.boxC p.nomargin {
+    margin: 0;
+}
+
+.boxC p.info-box-follow-up-links {
+    margin: 0;
+    text-align: right;
+}
+
+.pager {
+    float: left;
+    margin-bottom: 16px;
+    margin-top: 10px;
+}
+
+.pagesize {
+    float: right;
+    margin-bottom: 16px;
+    margin-top: 10px;
+}
+
+.paginator {
+    font: 12px sans-serif;
+    padding: 5px 0 10px;
+}
+
+.paginator .prev a, .paginator .prev a:visited, .paginator .next a, .paginator .next a:visited {
+    background-color: #FFFFFF;
+    border: 1px solid #FFFFFF;
+    color: #777777;
+    font: bold 100% sans-serif;
+    padding: 2px 4px 3px;
+}
+
+.paginator .prev {
+    margin-right: 0.5em;
+}
+
+.paginator .next {
+    margin-left: 0.5em;
+}
+
+.paginator .page, .paginator .page a:visited, .paginator .curr {
+    background-color: #FFFFFF;
+    border: 1px solid #CCCCCC;
+    color: #777777;
+    font: 0.875em verdana;
+    margin: 0 0.25em;
+    padding: 0.25em;
+}
+
+.paginator .curr {
+    background-color: #777777;
+    border: 1px solid #777777;
+    color: #FFFFFF;
+    font-weight: bold;
+}
+
+.paginator .page:hover, .paginator .prev a:hover, .paginator .next a:hover {
+    background-color: #777777;
+    border: 1px solid #777777;
+    color: #FFFFFF;
+    text-decoration: none;
+}
+
+.paginator .text {
+    color: #777777;
+    font: bold 100% sans-serif;
+    padding: 0.3em;
+}
+
+.paginator-container-left {
+    padding: 5px 0 10px;
+}
+
+.tags {
+    display: block;
+    font-family: sans-serif;
+    line-height: 200%;
+    margin-top: 5px;
+}
+
+.tags a, span.tag {
+    background-color: #EEEEEE;
+    border-bottom: 1px solid #CCCCCC;
+    border-right: 1px solid #CCCCCC;
+    color: #777777;
+    font-size: 11px;
+    font-weight: normal;
+    padding: 1px 8px;
+    text-decoration: none;
+    white-space: nowrap;
+}
+
+.tags a:hover {
+    background-color: #356FCB;
+    color: #FFFFFF;
+}
+
+.tag-number {
+    font-family: sans-serif;
+    font-weight: 700;
+}
+
+.marked-tags {
+    margin-bottom: 5px;
+    margin-top: 0;
+}
+
+a.medal {
+    background: none repeat scroll 0 0 #FFFFCD;
+    border-color: #EEEEEE #CCCCCC #CCCCCC #EEEEEE;
+    border-left: 1px solid #EEEEEE;
+    border-style: solid;
+    border-width: 1px;
+    color: #333333;
+    font-size: 14px;
+    font-weight: bold;
+    line-height: 250%;
+    padding: 4px 12px 4px 6px;
+    text-decoration: none;
+}
+
+a.medal:hover {
+    background: url("../images/medala_on.gif") no-repeat scroll 0 0 transparent;
+    border-color: #E7E296 #D1CA3D #D1CA3D #E7E296;
+    border-left: 1px solid #E7E296;
+    border-style: solid;
+    border-width: 1px;
+    color: #333333;
+    text-decoration: none;
+}
+
+.tabBar {
+    background-color: #FFFFFF;
+    border-bottom: 1px solid white;
+    clear: both;
+    height: 30px;
+    margin-bottom: 3px;
+    width: 100%;
+}
+
+.tabsA {
+    background-color: #FFFFFF;
+    display: block;
+    float: right;
+    font-weight: bold;
+    height: 20px;
+    position: relative;
+}
+
+.tabsA a, .sticky-sort-tabs {
+    background: none repeat scroll 0 0 #EEEEEE;
+    border-bottom: 1px solid #CCCCCC;
+    border-right: 1px solid #CCCCCC;
+    color: #888A85;
+    display: block;
+    float: left;
+    height: 20px;
+    line-height: 22px;
+    margin: 5px 4px 0 0;
+    text-decoration: none;
+}
+
+.tabsA a {
+    padding: 0 11px;    
+}
+
+.sticky-sort-tabs {
+    width: 20px;
+    padding: 0;
+}
+
+.sticky-sort-tabs input {
+    border: 0;
+    height: 14px;
+    width: 14px;
+    margin: 2px;
+}
+
+.tabsA a.on, .tabsA a:hover {
+    background: none repeat scroll 0 0 #FFFFFF;
+    color: #A40000;
+}
+
+.tabsA a:hover {
+    background: none repeat scroll 0 0 #356FCB;
+    color: #FFFFFF;
+}
+
+.headlineA {
+    border-bottom: 1px solid #777777;
+    font-size: 13px;
+    font-weight: 800;
+    height: 30px;
+    margin-bottom: 12px;
+    padding-bottom: 2px;
+    text-align: right;
+}
+
+.headQuestions {
+    background: url("../images/dot-list.gif") no-repeat scroll left center transparent;
+    border-bottom: 0 solid #777777;
+    float: left;
+    font-size: 15px;
+    font-weight: 700;
+    height: 23px;
+    line-height: 23px;
+    margin: 5px 0 0 5px;
+    padding: 0 6px 0 15px;
+}
+
+.headUsers {
+    background: url("../images/dot-list.gif") no-repeat scroll left center transparent;
+    border-bottom: 0 solid #777777;
+    float: left;
+    font-size: 15px;
+    font-weight: 700;
+    height: 23px;
+    line-height: 23px;
+    margin: 5px 0 0 5px;
+    padding: 0 6px 0 15px;
+}
+
+.headMedals {
+    background: url("../images/dot-list.gif") no-repeat scroll left center transparent;
+    border-bottom: 0 solid #777777;
+    float: left;
+    font-size: 15px;
+    font-weight: 700;
+    height: 23px;
+    line-height: 23px;
+    margin: 5px 0 0 5px;
+    padding: 0 6px 0 15px;
+}
+
+.headNormal {
+    border-bottom: 1px solid #777777;
+    font-size: 15px;
+    font-weight: bold;
+    margin-bottom: 12px;
+    padding: 3px;
+    text-align: left;
+}
+
+.headUser {
+    border-bottom: 1px solid #777777;
+    font-size: 20px;
+    font-weight: 800;
+    margin-bottom: 12px;
+    padding: 5px;
+    text-align: left;
+}
+
+.questions-related {
+    font-weight: 700;
+    word-wrap: break-word;
+}
+
+.questions-related p {
+    font-size: 100%;
+    line-height: 20px;
+    margin-bottom: 10px;
+}
+
+.question-body {
+    font-size: 13px;
+    line-height: 20px;
+    min-height: 100px;
+}
+
+.question-body img {
+    max-width: 640px;
+}
+
+.vote-buttons {
+    float: left;
+    text-align: center;
+}
+
+span.form-error {
+    color: #990000;
+    font-weight: normal;
+    margin-left: 5px;
+}
+
+ul.errorlist li {
+    color: #990000;
+    font-weight: normal;
+    margin-left: 0px;
+    margin-top: 5px;
+}
+
+.answer {
+    border-bottom: 1px solid #CCCCCE;
+    padding-top: 10px;
+    width: 100%;
+}
+
+.answer-body {
+    font-size: 13px;
+    line-height: 20px;
+    min-height: 80px;
+}
+
+.answer-body img {
+    max-width: 640px;
+}
+
+.answered-by-owner {
+    background: none repeat scroll 0 0 #E9E9FF;
+}
+
+.accepted-answer {
+    background-color: #EBFFE6;
+    border-bottom-color: #9BD59B;
+}
+
+.answered {
+    background: none repeat scroll 0 0 #E5EBF8;
+    color: #314362;
+}
+
+.answered-accepted, .answer-votes.answered-accepted {
+    background: none repeat scroll 0 0 #E6F8DD;
+    color: #3A6231;
+}
+
+.unanswered {
+    background: none repeat scroll 0 0 #F3E3E1;
+    color: #6B2B28;
+}
+
+.tagsList {
+    list-style-type: none;
+    margin: 0;
+    min-height: 360px;
+    padding: 0;
+}
+
+.tagsList li {
+    float: left;
+    width: 235px;
+}
+
+.badge-list {
+    list-style-type: none;
+    margin: 0;
+}
+
+.badge-list a {
+    color: #3060A8;
+}
+
+.badge-list a.medal {
+    color: #333333;
+}
+
+.list-item {
+    margin-left: 15px;
+}
+
+.list-item li {
+    font-size: 13px;
+    line-height: 20px;
+    list-style-type: disc;
+    margin-bottom: 10px;
+}
+
+.form-row {
+    line-height: 25px;
+}
+
+table.form-as-table {
+    margin-top: 5px;
+}
+
+table.form-as-table ul {
+    display: inline;
+    list-style-type: none;
+}
+
+table.form-as-table li {
+    display: inline;
+}
+
+table.form-as-table pre {
+    display: inline;
+}
+
+table.check-table td {
+    padding-right: 50px;
+}
+
+.submit-row {
+    clear: both;
+    display: block;
+    line-height: 30px;
+    padding-top: 10px;
+}
+
+.error {
+    color: darkred;
+    font-size: 10px;
+    margin: 0;
+}
+
+.small {
+    font-size: 11px;
+}
+
+span.form-error {
+    color: #990000;
+    font-size: 90%;
+    font-weight: normal;
+    margin-left: 5px;
+}
+
+.title-desc {
+    color: #666666;
+    font-size: 90%;
+}
+
+#editor {
+    font-size: 100%;
+    line-height: 18px;
+    min-height: 200px;
+    width: 100%;
+}
+
+.wmd-preview {
+    background-color: #F5F5F5;
+    margin-top: 10px;
+    min-height: 20px;
+    padding: 6px;
+    width: 98%;
+}
+
+.preview-toggle {
+    color: #AAAAAA;
+    font-weight: 600;
+    text-align: left;
+    width: 100%;
+}
+
+.preview-toggle span:hover {
+    cursor: pointer;
+}
+
+#revisions {
+    width: 950px;
+}
+
+.revision {
+    font-size: 13px;
+    margin: 10px 0;
+    width: 100%;
+}
+
+.revision .header {
+    background-color: #EEEEEE;
+    cursor: pointer;
+    padding: 5px;
+}
+
+.revision .author {
+    background-color: #E9E9FF;
+}
+
+.revision .summary {
+    padding: 5px 0 10px;
+}
+
+.revision .summary span {
+    /**background-color: yellow;**/
+    display: inline;
+    padding-left: 3px;
+    padding-right: 3px;
+}
+
+.revision h1 {
+    font-size: 130%;
+    font-weight: 600;
+    padding: 15px 0;
+}
+
+.revision-mark {
+    display: inline-block;
+    font-size: 90%;
+    overflow: hidden;
+    text-align: left;
+    width: 200px;
+}
+
+.revision-number {
+    font-family: sans-serif;
+    font-size: 300%;
+    font-weight: bold;
+}
+
+.revision .body {
+    margin-bottom: 50px;
+    padding-left: 10px;
+}
+
+del {
+    color: #FF5F5F;
+}
+
+ins {
+    background-color: #97FF97;
+}
+
+.count {
+    color: #777777;
+    font-family: Arial;
+    font-size: 200%;
+    font-weight: 700;
+}
+
+.scoreNumber {
+    color: #777777;
+    font-family: Arial;
+    font-size: 35px;
+    font-weight: 800;
+    line-height: 40px;
+}
+
+.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("../images/edit.png") no-repeat scroll 0 0 transparent;
+    padding-left: 20px;
+}
+
+.user-info-table {
+    margin-bottom: 10px;
+}
+
+.relativetime {
+    text-decoration: none;
+}
+
+.answer-summary {
+    clear: both;
+    display: block;
+    padding: 3px;
+}
+
+.answer-votes {
+    background-color: #EEEEEE;
+    color: #555555;
+    float: left;
+    font-family: Arial;
+    font-size: 110%;
+    font-weight: bold;
+    height: 15px;
+    margin-right: 10px;
+    padding: 4px 4px 5px;
+    text-align: center;
+    text-decoration: none;
+    width: 20px;
+}
+
+.vote-count {
+    color: #777777;
+    font-family: Arial;
+    font-size: 160%;
+    font-weight: 700;
+}
+
+.user-action-1 {
+    color: #333333;
+    font-weight: bold;
+}
+
+.user-action-2 {
+    color: #CCCCCC;
+    font-weight: bold;
+}
+
+.user-action-3 {
+    color: #333333;
+}
+
+.user-action-4 {
+    color: #333333;
+}
+
+.user-action-7 {
+    color: #333333;
+}
+
+.user-action-8 {
+    background-color: #CCCCCC;
+    color: #763333;
+    font-weight: bold;
+    padding: 3px;
+}
+
+.question-title-link a {
+    color: #0077CC;
+    font-weight: bold;
+}
+
+.answer-title-link a {
+    color: #333333;
+}
+
+.post-type-1 a {
+    font-weight: bold;
+}
+
+.post-type-3 a {
+    font-weight: bold;
+}
+
+.post-type-2 a {
+    color: #333333;
+}
+
+.post-type-4 a {
+    color: #333333;
+}
+
+.post-type-8 a {
+    color: #333333;
+}
+
+.badge1 {
+    color: #FFCC00;
+}
+
+.silver, .badge2 {
+    color: #CCCCCC;
+}
+
+.bronze, .badge3 {
+    color: #CC9933;
+}
+
+.score {
+    color: #333333;
+    font-size: 110%;
+    font-weight: bold;
+    margin-left: 3px;
+}
+
+.footerLinks {
+    color: #3060A8;
+    font-size: 13px;
+}
+
+.footerLinks a {
+    color: #3060A8;
+    font-size: 13px;
+}
+
+.user {
+    line-height: 140%;
+    padding: 5px;
+    width: 170px;
+    display: inline-block;
+}
+
+.user ul {
+    list-style-type: none;
+    margin: 0;
+}
+
+.user .thumb {
+    clear: both;
+    display: inline;
+    float: left;
+    margin-right: 4px;
+}
+
+.message {
+    background-color: #EEEEEE;
+    border: 1px solid #AAAAAA;
+    margin: 10px 0;
+    padding: 5px;
+}
+
+.message p {
+    margin-bottom: 0;
+}
+
+.darkred {
+    color: darkred;
+}
+
+.submit {
+    background-color: #D4D0C8;
+    border: 1px solid #777777;
+    cursor: pointer;
+    font-size: 120%;
+    font-weight: bold;
+    height: 40px;
+    padding-bottom: 4px;
+}
+
+.submit:hover {
+    text-decoration: underline;
+}
+
+.ask-body {
+    padding-right: 10px;
+}
+
+.notify {
+    background-color: #F4A83D;
+    color: #444444;
+    font-weight: bold;
+    left: 0;
+    padding: 0;
+    position: fixed;
+    text-align: center;
+    top: 0;
+    width: 100%;
+    z-index: 100;
+}
+
+.notify p {
+    font-size: 16px;
+    margin-bottom: 5px;
+    margin-top: 5px;
+}
+
+#close-notify {
+    background-color: #FAD163;
+    border: 2px solid #735005;
+    color: #735005;
+    cursor: pointer;
+    font-size: 14px;
+    line-height: 18px;
+    padding: 0 3px;
+    position: absolute;
+    right: 5px;
+    text-decoration: none;
+    top: 5px;
+}
+
+#close-notify:hover {
+    text-decoration: none;
+}
+
+.big {
+    font-size: 15px;
+}
+
+.strong {
+    font-weight: bold;
+}
+
+.orange {
+    color: #D64000;
+    font-weight: bold;
+}
+
+.grey {
+    color: #808080;
+}
+
+.about div {
+    border-top: 1px dashed #AAAAAA;
+    padding: 10px 5px;
+}
+
+.about div.first {
+    border-top: medium none;
+    padding-top: 0;
+}
+
+.about p {
+    margin-bottom: 10px;
+}
+
+.about a {
+    color: #D64000;
+    text-decoration: underline;
+}
+
+.about h3 {
+    font-size: 15px;
+    font-weight: 700;
+    line-height: 30px;
+    padding-top: 0;
+}
+
+.nomargin {
+    margin: 0;
+}
+
+.inline-block {
+    display: inline-block;
+}
+
+.list-table td {
+    vertical-align: top;
+}
+
+table.form-as-table input {
+    display: inline;
+    margin-left: 4px;
+}
+
+ul.form-horizontal-rows {
+    list-style: none outside none;
+    margin: 0;
+}
+
+ul.form-horizontal-rows li {
+    height: 40px;
+    position: relative;
+}
+
+ul.form-horizontal-rows label {
+    display: inline-block;
+}
+
+ul.form-horizontal-rows label {
+    bottom: 6px;
+    font-size: 12px;
+    left: 0;
+    line-height: 12px;
+    margin: 0;
+    position: absolute;
+}
+
+ul.form-horizontal-rows li input {
+    bottom: 0;
+    left: 180px;
+    margin: 0;
+    position: absolute;
+}
+
+#changepw-form li input {
+    left: 150px;
+}
+
+.user-profile-tool-links {
+    font-weight: bold;
+    padding-bottom: 10px;
+}
+
+.post-controls, .tags-container {
+    font-size: 11px;
+    line-height: 12px;
+    margin-bottom: 5px;
+    min-width: 200px;
+}
+
+.tags-container {
+    margin: 0 0 16px 0;
+}
+
+.post-controls {
+    float: left;
+}
+
+#question-controls .tags {
+    margin: 0 0 3px;
+}
+
+.post-update-info {
+    display: inline-block;
+    float: right;
+    margin-bottom: 5px;
+    width: 190px;
+}
+
+.post-update-info p {
+    font-size: 11px;
+    line-height: 15px;
+    margin: 0 0 4px;
+    padding: 0;
+}
+
+.post-update-info img {
+    float: left;
+    margin: 4px 8px 0 0;
+    width: 32px;
+}
+
+#tagSelector {
+    padding-bottom: 2px;
+}
+
+#hideIgnoredTagsControl {
+    margin: 5px 0 0;
+}
+
+#hideIgnoredTagsCb {
+    margin: 0 2px 0 1px;
+}
+
+a.sidebar_button {
+    background: none repeat scroll 0 0 #EEEEEE;
+    color: black;
+    cursor: pointer;
+    font-size: 11px;
+    padding: 3px;
+}
+
+a.sidebar_button:hover {
+    background-color: #777777;
+    color: white;
+    text-decoration: none;
+}
+
+a.post-vote, .favorite-mark, a.accept-answer {
+    display: block;
+    height: 24px;
+    position: relative;
+    width: 24px;
+}
+
+a.post-vote.up {
+    background: url("../images/vote-arrow-up.png") no-repeat scroll center center transparent;
+}
+
+a.post-vote.up.on, a.post-vote.up:hover {
+    background: url("../images/vote-arrow-up-on.png") no-repeat scroll center center transparent;
+}
+
+a.post-vote.down {
+    background: url("../images/vote-arrow-down.png") no-repeat scroll center center transparent;
+}
+
+a.post-vote.down.on, a.post-vote.down:hover {
+    background: url("../images/vote-arrow-down-on.png") no-repeat scroll center center transparent;
+}
+
+a.accept-answer {
+    background: url("../images/vote-accepted.png") no-repeat scroll center center transparent;
+}
+
+a.accept-answer.on, a.accept-answer:hover {
+    background: url("../images/vote-accepted-on.png") no-repeat scroll center center transparent;
+}
+
+.community-wiki {
+    font-size: 11px;
+    color: #333;
+    background: url("../images/wiki.png") no-repeat left center;
+    padding-left: 36px;
+    margin: 6px 0 0 0;
+    min-height: 32px;
+    line-height: 15px;
+}
+
+.post-score, .comments-char-left-count {
+    color: #777777;
+    font-family: Arial;
+    font-size: 165%;
+    font-weight: bold;
+    padding: 0 0 3px;
+}
+
+.favorite-mark {
+    background: url("../images/vote-favorite-off.png") no-repeat scroll center center transparent;
+}
+
+.favorite-mark.on, a.favorite-mark:hover {
+    background: url("../images/vote-favorite-on.png") no-repeat scroll center center transparent;
+}
+
+.favorite-count {
+    color: #777777;
+    font-family: Arial;
+    font-size: 100%;
+    font-weight: bold;
+    padding: 0;
+}
+
+.comments-container {
+    clear: both;
+}
+
+.comments-container {
+    padding: 0;
+}
+
+.answered-by-owner .comments-container {
+    background-color: #E6ECFF;
+}
+
+.accepted-answer .comments-container {
+    background-color: #CCFFBF;
+}
+
+.comment {
+    border-top: 1px dotted #CCCCCE;
+    margin: 0;
+    position: relative;
+}
+
+.comment.not_top_scorer {
+    display: none;
+}
+
+.comment-score {
+    color: #777777;
+    font-family: Arial;
+    font-size: 16px;
+    font-weight: bold;
+    padding-top: 3px;
+    vertical-align: top;
+    float: left;
+    width: 22px;
+    height: 100%;
+    text-align: center;
+}
+
+.comment-text {
+    color: #444444;
+    font-size: 12px;
+    margin: 0 0 0 22px;
+    padding: 0;
+}
+
+.comment-text p {
+    font-size: 12px;
+}
+
+.comment-info {
+    font-size: 11px;
+    margin: 0 0 4px 0;
+    text-align: right;
+    height: 18px;
+    vertical-align: middle;
+}
+
+.comment-info * {
+    float: right;
+    height: 18px;
+    margin-left: 4px;
+}
+
+a.comment-like, a.comment-delete, a.comment-edit, a.comment-convert {
+    margin-left: 2px;
+    width: 18px;
+}
+
+a.comment-like {
+    background: url("../images/comment-like.png") no-repeat scroll center center transparent;
+}
+
+a.comment-like:hover, a.comment-like.on {
+    background: url("../images/comment-like-on.png") no-repeat scroll center center transparent;
+}
+
+a.comment-delete {
+    background: url("../images/comment-delete.png") no-repeat scroll center center transparent;
+}
+
+a.comment-delete:hover {
+    background: url("../images/comment-delete-hover.png") no-repeat scroll center center transparent;
+}
+
+a.comment-convert {
+    background: url("../images/convert-off.png") no-repeat scroll center center transparent;
+}
+
+a.comment-convert:hover {
+    background: url("../images/convert-hover.png") no-repeat scroll center center transparent;
+}
+
+a.comment-edit {
+    background: url("../images/comment-edit.png") no-repeat scroll center center transparent;
+}
+
+a.comment-edit:hover {
+    background: url("../images/comment-edit-hover.png") no-repeat scroll center center transparent;
+}
+
+img.subscription-remove {
+    float:right;
+}
+
+.comment-form-container {
+    display: none;
+    padding-top: 12px;
+}
+
+.comment-form-widgets-container input {
+    vertical-align: top;
+}
+
+.comment-form-widgets-container textarea {
+    height: 80px;
+    width: 80%;
+    float: left;
+}
+
+span.comment-chars-left {
+    font-size: 11px;
+    margin-right: 20px;
+}
+
+div.comment-tools {
+    border-top: 1px dotted #CCCCCE;
+    padding-top: 12px;
+    text-align: right;
+}
+
+div.comment-tools .comments-showing {
+    color: #777777;
+    font-size: 11px;
+}
+
+div.comment-tools a {
+    background: none repeat scroll 0 0 #EEEEEE;
+    color: black;
+    cursor: pointer;
+    font-size: 11px;
+    padding: 3px;
+}
+
+div.comment-tools a:hover {
+    background-color: #777777;
+    color: white;
+    text-decoration: none;
+}
+
+.action-link {
+    color: #777777;
+    cursor: pointer;
+    padding: 3px;
+}
+
+.action-link a {
+    color: inherit;
+}
+
+.action-link a.ajax-command:hover {
+    background-color: #777777;
+    color: #FFFFFF;
+    text-decoration: none;
+}
+
+.action-link-separator {
+    color: #CCCCCC;
+}
+
+.deleted {
+    background-color: #F4E7E7;
+}
+
+#command-loader {
+    position: fixed;
+    bottom: 0px;
+    left: 0px;
+    width: 24px;
+    height: 24px;
+    background: url('/m/default/media/images/indicator.gif')
+}
+
+#command-loader.success {
+    background: url('/m/default/media/images/vote-accepted-on.png')
+}
+
+.comment-form-buttons {
+    width: 18%;
+    height: 100%;
+    float: right;
+}
+
+.comment-form-buttons input, .user-prompt .prompt-buttons button {
+    height: 16px;
+    line-height: 12px;
+    font-size: 110%;
+    border: 1px solid #999;
+}
+
+.comment-form-buttons input {
+    width: 100%;
+    height: 22px;
+    vertical-align: middle;
+    margin-top: 6px;
+}
+
+.comments-char-left-count.warn {
+    color: orange;
+}
+
+#ask-related-questions {
+    max-height: 150px;
+    overflow-y: auto;
+}
+
+.context-menu {
+    position: relative;
+}
+
+div.dialog, .context-menu-dropdown {
+    position: absolute;
+    background-color: #EEEEEE;
+    -moz-border-radius: 5px;
+    -webkit-border-radius: 5px;
+    -moz-box-shadow: 2px 2px 5px #3060A8;
+    -webkit-box-shadow: 2px 2px 5px #3060A8;
+}
+
+.context-menu-dropdown {
+    display: none;
+    right: 0px;
+    top: 1.5em;
+    text-align: left;
+    list-style-type: none;
+    z-index: 500;
+}
+
+.context-menu-dropdown li.item {
+    padding: 4px 8px 4px 8px;
+    -moz-border-radius: 5px;
+    -webkit-border-radius: 5px;
+}
+
+.context-menu-dropdown li.item a {
+    color: inherit;
+    white-space: nowrap;
+    text-decoration: none;
+}
+
+.context-menu-dropdown li.separator {
+    text-align: center;
+    padding: 10px 0 4px 0;
+    font-size: 120%;
+    font-weight: bold;
+}
+
+.context-menu-dropdown li.item:hover {
+    background-color: #3060A8;
+    color: white;
+}
+
+.context-menu-dropdown span {
+    margin-right: 4px;
+    float: left;
+    width: 16px;
+    height: 16px;
+}
+
+.context-menu-trigger {
+    cursor: pointer;
+}
+
+div.dialog .dialog-content {
+    padding: 12px 12px 37px 12px;
+    z-index: 1000;
+}
+
+div.dialog .dialog-buttons {
+    margin: 0px;
+    height: 25px;
+    text-align: center;
+    position: absolute;
+    bottom: 0px;
+    left: 0px;
+    width: 100%;
+}
+
+.dialog-yes, .dialog-no {
+    margin: 0 3px 5px 3px;
+    -moz-border-radius: 3px;
+    -webkit-border-radius: 3px;
+    background-color: #3060A8;
+    color: white;
+    height: 20px;
+    line-height: 20px;
+    font-weight: bold;
+    border: 0;
+}
+
+div.dialog.confirm, div.dialog.warning {
+    text-align: center;
+}
+
+div.dialog.confirm {
+    font-size: 140%;
+    font-weight: bold;
+}
+
+div.dialog.prompt {
+    width: 300px;
+}
+
+div.dialog.prompt .dialog-content select, div.dialog.prompt .dialog-content textarea, div.dialog.prompt .dialog-content input[type=text] {
+    width: 100%;
+    padding: 0;
+    border: 0;
+}
+
+.user-prompt .prompt-buttons {
+    text-align: right;
+}
+
+.suspended-user {
+    text-decoration: line-through;
+}
+
+.feed-icon {
+    width: 14px;
+    height: 14px;
+    display: inline-block;
+}
+
+div#subscription_list {
+    width: 100%;
+    /*float:left;*/
+}
+
+div.subscription_summary {
+    border-top: 2px dotted #CCCCCE;
+    overflow: hidden;
+    padding: 3px 0px 5px 0;
+    position: relative;
+    width:100%;
+    margin-top: 5px;
+}
+
+div.subscription_title {
+    /*float:left;
+    line-height:30px;*/
+    margin-top: 5px;
+    font-size: 16px;
+    font-weight:bold;
+}
+
+a.subscription_unsubscribe_button {
+    float:left;
+    font-size: 11px;
+    font-weight:bold;
+
+    margin-right:15px;
+    margin-top: 5px;
+}
+
+div.subscription_userinfo {
+    float:right;
+}
+
+div.subscription_tags {
+    font-family: sans-serif;
+    float:left;
+}
+div.subscription_tags a, span.tag {
+    background-color: #EEEEEE;
+    border-bottom: 1px solid #CCCCCC;
+    border-right: 1px solid #CCCCCC;
+    color: #777777;
+    font-size: 11px;
+    font-weight: normal;
+    padding: 1px 8px;
+    text-decoration: none;
+    white-space: nowrap;
+}
+div.subscription_tags a:hover {
+    background-color: #356FCB;
+    color: #FFFFFF;
+}
+
+div.wmd-button {
+    color:white;
+}
+div.wmd-button-bar {
+    float:left;
+}
diff --git a/forum/modules/template_loader.py/forum/skins/default/media/style/user.css b/forum/modules/template_loader.py/forum/skins/default/media/style/user.css
new file mode 100644 (file)
index 0000000..f4fff84
--- /dev/null
@@ -0,0 +1,81 @@
+#user-menu-container {
+    position: relative;
+    text-align: right;
+}
+
+#user-menu {
+    cursor: pointer;
+    height: 1em;
+    font-size: 120%;
+    font-weight: bold;
+    color: #3060A8;
+}
+
+#user-menu-dropdown {
+    position: absolute;
+    background-color: #EEEEEE;
+    -moz-border-radius: 5px;
+    -webkit-border-radius: 5px;
+    -moz-box-shadow: 2px 2px 5px #3060A8;
+    -webkit-box-shadow: 2px 2px 5px #3060A8;
+}
+
+div.dialog.award-rep-points table {
+    margin: auto;
+    margin-top: 8px;
+}
+
+div.dialog.award-rep-points table th {
+    text-align: left;
+}
+
+div.dialog.award-rep-points table input, div.dialog.award-rep-points table textarea {
+    width: 150px;
+    max-height: 35px;
+}
+
+#user-menu-dropdown {
+    display: none;
+    right: 0px;
+    top: 1.5em;
+    text-align: left;
+    list-style-type: none;
+}
+
+#user-menu-dropdown li.item {
+    padding: 4px 8px 4px 8px;
+     -moz-border-radius: 5px;
+    -webkit-border-radius: 5px;
+}
+
+#user-menu-dropdown li.item a {
+    color: inherit;
+    white-space: nowrap;
+    text-decoration: none;
+}
+
+#user-menu-dropdown li.separator {
+    text-align: center;
+    padding: 10px 0 4px 0;
+    font-size: 120%;
+    font-weight: bold;
+}
+
+#user-menu-dropdown li.item:hover {
+    background-color: #3060A8;
+    color: white;
+}
+
+#user-menu-dropdown span {
+    margin-right: 4px;
+    float: left;
+    width: 16px;
+    height: 16px;
+}
+
+.user-auth { background: url('/m/default/media/images/user-sprite.png') no-repeat 0 0; }
+.user-award_rep { background: url('/m/default/media/images/user-sprite.png') no-repeat 0 -17px; }
+.user-edit { background: url('/m/default/media/images/user-sprite.png') no-repeat 0 -34px; }
+.user-moderator { background: url('/m/default/media/images/user-sprite.png') no-repeat 0 -51px; }
+.user-subscriptions { background: url('/m/default/media/images/user-sprite.png') no-repeat 0 -68px; }
+.user-superuser { background: url('/m/default/media/images/user-sprite.png') no-repeat 0 -85px; }
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/401.html b/forum/modules/template_loader.py/forum/skins/default/templates/401.html
new file mode 100644 (file)
index 0000000..7c1023f
--- /dev/null
@@ -0,0 +1,46 @@
+{% extends "base_content.html" %}
+{% load i18n %}
+{% block title %}{% trans "Not logged in" %}{% endblock %}
+{% block meta %}
+    <!-- <meta http-equiv="refresh" content="5;url={% url auth_signin %}"> -->
+{% endblock %}
+{% block forestyle%}
+    <style type="text/css">
+               form input { margin-right: 5px; }
+       </style>
+{% endblock %}
+{% block forejs %}
+       <script type="text/javascript">
+        $().ready(function(){
+            window.setInterval(function() {
+                $('#redirect_loader').html($('#redirect_loader').html() + '.')
+            }, 800);
+
+            window.setTimeout(function() {
+                window.location = "{% url auth_signin %}";
+            }, 5000);
+        });
+
+        </script>
+{% endblock %}
+{% block content %}
+<div id="main-bar" class="headNormal">
+    {% trans "Not logged in" %}
+</div>
+<div id="main-body" class="">
+    <div style="padding:5px 0px 10px 0;line-height:25px;">
+        <h3>{% trans "You are not logged in..." %}</h3>
+        <div style="margin-top:5px">
+            {% trans "...and the resource you're trying to access is protected." %}
+            <p>
+                {% trans "Redirecting to the login page." %}<span id="redirect_loader"></span>
+            </p>
+            <p>
+                {% trans "If you're not automatically redirected in 5 seconds, please click" %}
+                <a href="{% url auth_signin %}">{% trans "here" %}</a>.
+            </p>
+        </div>
+    </div>
+
+</div>
+{% endblock %}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/403.html b/forum/modules/template_loader.py/forum/skins/default/templates/403.html
new file mode 100644 (file)
index 0000000..26b563f
--- /dev/null
@@ -0,0 +1,36 @@
+{% extends "base_content.html" %}
+{% load i18n %}
+{% block title %}{% trans "Forbidden" %}{% endblock %}
+{% block forestyle%}
+    <style type="text/css">
+               form input { margin-right: 5px; }
+       </style>
+{% endblock %}
+{% block content %}
+<div id="main-bar" class="headNormal">
+    {% trans "Forbidden" %}
+</div>
+<div id="main-body" class="">
+    <div style="padding:5px 0px 10px 0;line-height:25px;">
+        <h3>{% trans "Sorry, you don't have permissions to access this page." %}</h3>
+        <div style="margin-top:5px">
+        {% trans "This might have happened for the following reasons:" %}<br/>
+            <ul>
+            <li>{% trans "you followed a link on an email, but you're currently logged in as another user;" %}</li>
+            <li>{% trans "there are errors in the url, please confirm it;" %}</li>
+            <li>{% trans "if you believe you shouldn't bee seeing this error, please" %}
+                               <a href="{% if settings.CONTACT_URL %}{{ settings.CONTACT_URL }}{% else %}{% url feedback %}{% endif %}" target="_blank">
+                                   {% trans "report this problem" %}
+                               </a>
+                       </li>
+            </ul>
+        </div>
+        <ul>
+            <li><a href="{% url index %}">{% trans "to home page" %} &raquo;</a></li>
+            <li><a href="{% url questions %}">{% trans "see all questions" %} &raquo;</a></li>
+            <li><a href="{% url tags %}">{% trans "see all tags" %} &raquo;</a></li>
+        </ul>
+    </div>
+
+</div>
+{% endblock %}
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/404.html b/forum/modules/template_loader.py/forum/skins/default/templates/404.html
new file mode 100644 (file)
index 0000000..ad2ac68
--- /dev/null
@@ -0,0 +1,48 @@
+{% extends "base_content.html" %}
+<!-- template 404.html -->
+{% load i18n %}
+{% block title %}{% trans "404 Error" %}{% endblock %}
+{% block forestyle%}
+    <style type="text/css">
+               form input { margin-right: 5px; }
+       </style>
+{% endblock %}
+{% block forejs %}
+       <script type="text/javascript">
+        $().ready(function(){
+            $("#linkPrevious").bind("click", back=function(){history.go(-1);})            
+        });
+         
+        </script>
+{% endblock %}
+{% block content %}
+<div id="main-bar" class="headNormal">
+    {% trans "404 Not Found" %}
+</div>
+<div id="main-body" class="">
+    <div style="padding:5px 0px 10px 0;line-height:25px;">
+        <h3>{% trans "Sorry, could not find the page you requested." %}</h3>
+        <div style="margin-top:5px">
+        {% trans "This might have happened for the following reasons:" %}<br/>
+            <ul>
+            <li>{% trans "this question or answer has been deleted;" %}</li>
+            <li>{% trans "url has error - please check it;" %}</li>
+            <li>{% trans "if you believe this error 404 should not have occurred, please" %} 
+                               <a href="{% if settings.CONTACT_URL %}{{ settings.CONTACT_URL }}{% else %}{% url feedback %}{% endif %}">{% trans "report this problem" %}</a></li>
+            </ul>
+        </div>
+        <script type="text/javascript">
+            var GOOG_FIXURL_LANG = '{{settings.LANGUAGE_CODE}}';
+            var GOOG_FIXURL_SITE = '{{site_url}}';
+        </script>
+        <script type="text/javascript" src="http://linkhelp.clients.google.com/tbproxy/lh/wm/fixurl.js"></script>
+        <ul>
+            <li><a href="#" id="linkPrevious">{% trans "back to previous page" %} &raquo;</a></li>
+            <li><a href="{% url questions %}">{% trans "see all questions" %} &raquo;</a></li>
+            <li><a href="{% url tags %}">{% trans "see all tags" %} &raquo;</a></li>
+        </ul>
+    </div>
+
+</div>
+{% endblock %}
+<!-- end template 404.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/500.html b/forum/modules/template_loader.py/forum/skins/default/templates/500.html
new file mode 100644 (file)
index 0000000..3300b8e
--- /dev/null
@@ -0,0 +1,35 @@
+{% extends "base_content.html" %}
+<!-- template 500.html -->
+{% load i18n %}
+{% block title %}{% spaceless %}500 Error{% endspaceless %}{% endblock %}
+{% block forejs %}
+        <script type="text/javascript">
+        $().ready(function(){
+            $("#linkPrevious").bind("click", back=function(){history.go(-1);})            
+        });
+         
+        </script>
+{% endblock %}
+{% block content %}
+<div id="main-bar" class="">
+    <h3>
+        500 Server Error
+    </h3>
+
+</div>
+<div id="main-body" class="headNormal">
+    <div style="padding:5px 0px 10px 0;line-height:25px">
+        <h3>{% trans "sorry, system error" %}</h3>
+        <br/>
+        {% trans "system error log is recorded, error will be fixed as soon as possible" %}<br/>
+               {% trans "please report the error to the site administrators if you wish" %}
+        <ul>
+            <li><a href="#" id="linkPrevious">{% trans "back to previous page" %}</a></li>
+            <li><a href="{% url questions %}">{% trans "see latest questions" %}</a></li>
+            <li><a href="{% url tags %}">{% trans "see tags" %}</a></li>
+        </ul>
+    </div>
+
+</div>
+{% endblock %}
+<!-- end template 500.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/503.html b/forum/modules/template_loader.py/forum/skins/default/templates/503.html
new file mode 100644 (file)
index 0000000..8f1664c
--- /dev/null
@@ -0,0 +1,22 @@
+{% load i18n %}
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+    <head>
+        <title>{% trans "System down for maintenance" %}</title>
+        <style>
+            #content {
+                margin: auto;
+            }
+        </style>
+    </head>
+    <body>
+        <div id="content">
+            <img src="{{ app_logo }}">
+            <p>{{ app_title }}</p>
+            <h3>{% trans "System down for maintenance" %}</h3>
+            <br/>
+            {{ message }}
+        </div>
+    </body>
+</html>
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/account_settings.html b/forum/modules/template_loader.py/forum/skins/default/templates/account_settings.html
new file mode 100644 (file)
index 0000000..d1349ec
--- /dev/null
@@ -0,0 +1,45 @@
+{% extends "base_content.html" %}
+<!-- settings.html -->
+{% load i18n %}
+{% block title %}{% spaceless %}{% trans "Account functions" %}{% endspaceless %}{% endblock %}
+{% block head %}
+<style type="text/css" media="screen">
+    h4 {font-size:12pt;}
+       dt, dd { padding:0 0 0.35em 0; }
+       dt { float: left; width: 21ex;  }
+       dd { margin-left: 23ex;  }
+       
+       #settings-options, #settings-intro { padding: 4em 1.5em;}
+       #settings-options { min-height: 300px; border-left: 1px solid #333;}
+       
+       #settings-options h5 { font-weight: bold;}
+</style>
+{% endblock %}
+
+{% block content %}
+<div id="main-bar">
+    <h3><strong>{{ request.user.username }} {% trans "Profile" %}</strong></h3>
+</div>
+<div id="settings-options">
+       {% if msg %}
+               <p class="error">{{ msg }}</p>
+       {% endif %}
+
+       <dl class="list-item">
+        <dt>&raquo; <a href="{% url user_changepw %}">{% trans "Change password" %}</a></dt>
+        <dd>{% trans "Give your  account a new password." %}</dd>
+        {% comment %}
+        <dt>&raquo; <a href="{% url user_changeemail %}">{% trans "Change email " %}</a></dt>
+        <dd>{% trans "Add or update the email address associated with your account." %}</dd>
+
+        <dt>&raquo; <a href="{% url user_changeopenid %}">{% trans "Change OpenID" %}</a></dt>
+        <dd>{% trans "Change openid associated to your account" %}</dd>
+
+        
+        <dt>&raquo; <a href="{% url user_delete %}">{% trans "Delete account" %}</a></dt>
+        <dd>{% trans "Erase your username and all your data from website" %}</dd>
+        {% endcomment %}
+       </dl>
+</div>
+{% endblock %}
+<!-- end settings.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/answer_edit.html b/forum/modules/template_loader.py/forum/skins/default/templates/answer_edit.html
new file mode 100644 (file)
index 0000000..985addd
--- /dev/null
@@ -0,0 +1,114 @@
+{% extends "base.html" %}
+<!-- template answer_edit.html -->
+{% load i18n %}
+{% load extra_tags %}
+{% block title %}{% spaceless %}{% trans "Edit answer" %}{% endspaceless %}{% endblock %}
+{% block forejs %}
+        <script type='text/javascript' src='{% media  "/media/js/wmd/showdown.js" %}'></script>
+        <script type='text/javascript' src='{% media  "/media/js/wmd/wmd.js" %}'></script>
+        <link rel="stylesheet" type="text/css" href="{% media  "/media/js/wmd/wmd.css" %}" />
+        <script type="text/javascript">
+        
+        $().ready(function(){
+            $("#nav_questions").attr('className',"on");
+            $('#editor').TextAreaResizer();
+
+
+            //toggle preview of editor
+            var display = true;
+            var txt = "{% trans "hide preview" %}";
+            $('#pre-collapse').text(txt);
+            $('#pre-collapse').bind('click', function(){
+                txt = display ? "{% trans "show preview" %}" : "{% trans "hide preview" %}";
+                display = !display;
+                $('#previewer').toggle();
+                $('#pre-collapse').text(txt);
+            });
+
+
+            $('#id_revision').unbind().change(function(){
+                $("#select_revision").click();
+            });
+
+
+            answer = $("textarea#editor")[0].value;
+        });
+
+
+        function submitClicked(e, f) {
+            if(!(browserTester('chrome') || browserTester('safari'))) {
+                $("input.submit")[0].disabled=true;
+                $("input.submit")[1].disabled=true;
+            }
+            window.removeEventListener('beforeunload', beforeUnload, true);
+            if (f) {
+                f.submit();
+            }
+        }
+
+        function beforeUnload(e) {
+            if($("textarea#editor")[0].value != answer) {
+                 return yourWorkWillBeLost(e);
+            }
+        }
+        window.addEventListener('beforeunload', beforeUnload, true);
+
+        var answer = "";
+        </script>
+{% endblock %}
+        
+{% block content %}
+<div id="main-bar" class="headNormal">
+    {% trans "Edit answer" %} [<a href="{{ answer.question.get_absolute_url }}#{{ answer.id }}">{% trans "back" %}</a>]
+</div>
+<div id="main-body" class="ask-body">
+    <div id="askform">
+        <form id="fmedit" action="{% url edit_answer answer.id %}" method="post" >
+            <label for="id_revision" ><strong>{% trans "revision" %}:</strong></label> <br/> 
+            {% if revision_form.revision.errors %}{{ revision_form.revision.errors.as_ul }}{% endif %}
+            <div>
+            {{ revision_form.revision }} <input type="submit" style="display:none" id="select_revision" name="select_revision" value="{% trans "select revision" %}">
+            </div>
+            <div class="form-item">
+                <div id="wmd-button-bar" class="wmd-panel"></div>
+                {{ form.text }}
+                <span class="form-error"></span>
+                <div class="preview-toggle"><span id="pre-collapse" 
+                                       title="{% trans "Toggle the real time Markdown editor preview" %}">{% trans "toggle preview" %}</span>
+                           <span style="text-align: right; margin-left: 200px;" id="editor-metrics"></span>
+                               {% if settings.WIKI_ON %}
+                    <div style="float:right;">
+                        {{ form.wiki }} <span style="color:#000;cursor:help" title="{{form.wiki.help_text}}">{{ form.wiki.label_tag }} </span>
+                    </div>
+                    {% endif %}
+                </div>
+                <div id="previewer" class="wmd-preview"></div>
+            </div>
+            
+            <strong>{{ form.summary.label_tag }}</strong> <br/>
+            {{ form.summary }}  {{ form.summary.errors }}
+            <div class="title-desc">
+                {{ form.summary.help_text }}
+            </div>
+            
+            {% if form.recaptcha %}
+            <div class="question-captcha">
+               {{ form.recaptcha.errors }}
+               {{ form.recaptcha }}
+            </div>
+            {% endif %}
+            
+            <input type="button" value="{% trans "Save edit" %}" class="submit" onclick="submitClicked(event, this.form)" />
+            <input type="button" value="{% trans "Cancel" %}" class="submit" onclick="submitClicked(event, this.form);history.back(-1);" />
+        </form>
+    </div>
+</div>
+{% endblock %}
+
+{% block sidebar %}
+{% include "answer_edit_tips.html" %}
+{% endblock %}
+
+{% block endjs %}
+{% endblock %}
+<!-- end template answer_edit.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/answer_edit_tips.html b/forum/modules/template_loader.py/forum/skins/default/templates/answer_edit_tips.html
new file mode 100644 (file)
index 0000000..39e1f3c
--- /dev/null
@@ -0,0 +1,26 @@
+<!-- template answer_edit_tips.html -->
+{% load i18n general_sidebar_tags %}
+<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>
+        <p class='info-box-follow-up-links'>
+            <a href="{% url faq %}" target="_blank" title="{% trans "see frequently asked questions" %}">faq &raquo;</a>
+        </p>
+    </div>
+</div>
+
+{% markdown_help %}
+<!-- end template answer_edit_tips.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/ask.html b/forum/modules/template_loader.py/forum/skins/default/templates/ask.html
new file mode 100644 (file)
index 0000000..fa38b76
--- /dev/null
@@ -0,0 +1,176 @@
+{% extends "base.html" %}
+<!-- template ask.html -->
+{% load i18n extra_tags extra_filters %}
+{% block title %}{% spaceless %}{% trans "Ask a question" %}{% endspaceless %}{% endblock %}
+{% block forejs %}
+        <script type='text/javascript' src='{% media  "/media/js/wmd/showdown.js" %}'></script>
+        <script type='text/javascript' src='{% media  "/media/js/wmd/wmd.js" %}'></script>
+        <link rel="stylesheet" type="text/css" href="{% media  "/media/js/wmd/wmd.css" %}" />
+        <script type="text/html" id="question-summary-template">
+            <div class="answer-summary">
+                <a href="%URL%"><div class="answer-votes">%SCORE%</div></a>
+                <div class="answer-link">
+                    <a class="question-hyperlink" href="%URL%" title="%SUMMARY%">%TITLE%</a>
+                </div>
+            </div>
+        </script>
+        <script type="text/javascript">
+        $(function(){
+            //set current module button style
+            $("#nav_ask").attr('className',"on");
+            $('#editor').TextAreaResizer();
+
+            //toggle preview of editor
+                       //todo remove copy-paste
+            var display = true;
+            var txt = "[{% trans "hide preview" %}]";
+            $('#pre-collapse').text(txt);
+            $('#pre-collapse').bind('click', function(){
+                txt = display ? "[{% trans "show preview" %}]" : "[{% trans "hide preview" %}]";
+                display = !display;
+                $('#previewer').toggle();
+                $('#pre-collapse').text(txt);
+            });
+
+            //Tags autocomplete action
+               $("#id_tags").autocomplete("/matching_tags/", {
+                minChars: 1,
+                       matchContains: true,
+                max: 10,
+                multiple: true,
+                multipleSeparator: " ",
+                highlightItem: true,
+                scroll: true,
+                scrollHeight: 300,
+
+
+                       /*
+                       formatItem: function(row, i, max) {
+                               return row.n + " ("+ row.c +")";
+                       },
+                formatResult: function(row, i, max){
+                    return row.n;
+                }
+                */
+
+                formatItem: function(row, i, max, value) {
+                    return row[1] + " (" + row[2] + ")";
+                },
+
+                formatResult: function(row, i, max, value){
+                    return row[1];
+                }
+
+            });
+
+        });
+
+        function submitClicked(e, f) {
+            if(!(browserTester('chrome') || browserTester('safari'))) {
+                $("input.submit")[0].disabled=true;
+            }
+            window.removeEventListener('beforeunload', beforeUnload, true);
+            if (f) {
+                f.submit();
+            }
+        }
+
+        function beforeUnload(e) {
+            if($("input#id_title")[0].value != "" || $("textarea#editor")[0].value != "" || $("input#id_tags")[0].value != "") {
+                return yourWorkWillBeLost(e);
+            }
+        }
+        window.addEventListener('beforeunload', beforeUnload, true);
+
+        var related_questions_url = "{% url related_questions %}";
+        </script>
+        <script src="{% media "/media/js/osqa.ask.js" %}" type="text/javascript"></script>
+{% endblock %}
+
+{% block content %}
+<div id="main-bar" class="headNormal">
+       {% trans "Ask a question" %}
+</div>
+<div id="main-body" class="ask-body">
+    <div id="askform">
+        <form id="fmask" action="" method="post" accept-charset="utf-8">
+                       {% if not request.user.is_authenticated %}
+            <div class="message">
+                <span class="strong big">{% trans "You are welcome to start submitting your question anonymously." %}</span>
+                <p>{% blocktrans %}
+                    After submiting your question, you will be redirected to the login/signup page.
+                    Your question will be saved in the current session and will be published after you login with your existing account,
+                    or signup for a new account{% endblocktrans %}{% if "ask"|contained_in:settings.REQUIRE_EMAIL_VALIDATION_TO %}
+                    {% trans "and validate your email." %}{% else %}.{% endif %}</p>
+            </div>
+            {% else %}
+                {% if not request.user.email_valid_and_can_ask %}
+                    <div class="message">
+                        {% blocktrans %}Remember, your question will not be published until you validate your email.{% endblocktrans %}
+                        <a href="{% url send_validation_email %}">{% trans "Send me a validation link." %}</a>
+                    </div>
+                {% endif %}
+                       {% endif %}
+            <div class="form-item">
+                <label for="id_title" ><strong>{{ form.title.label_tag }}:</strong></label> <span class="form-error"></span><br/>
+                {{ form.title }} {{ form.title.errors }}
+                <div class="title-desc">
+                    {{ form.title.help_text }}
+                </div>
+            </div>
+            <div id="ask-related-questions"></div>
+            <div class="form-item">
+                <div id="wmd-button-bar" class="wmd-panel"></div>
+                {{ form.text }} {{ form.text.errors }}
+                <div class="preview-toggle">
+                    <table width="100%">
+                        <tr>
+                            <td>
+                                <span id="pre-collapse" title="{% trans "Toggle the real time Markdown editor preview" %}">{% trans "toggle preview" %}</span>
+                            </td>
+                            <td style="text-align: right;" id="editor-metrics"></td>
+                            {% if settings.WIKI_ON %}
+                            <td class="tright">
+                                {{ form.wiki }} <span class="help_text" title="{{form.wiki.help_text}}">{{ form.wiki.label_tag }} </span>
+                            </td>
+                            {% endif %}
+                        </tr>
+
+                    </table>
+                </div>
+                <div id="previewer" class="wmd-preview"></div>
+                <span class="form-error"></span>
+            </div>
+            <div class="form-item">
+                <strong>{{ form.tags.label_tag }}:</strong> {% trans "(required)" %} <span class="form-error"></span><br/>
+                {{ form.tags }}  {{ form.tags.errors }}
+            </div>
+                       <p class="title-desc">
+                               {{ form.tags.help_text }}
+                       </p>
+                       
+            {% if form.recaptcha %}
+            <div class="question-captcha" style="float: left">
+               {{ form.recaptcha.errors }}
+               {{ form.recaptcha }}
+            </div>
+            <div class="clear"></div>
+            {% endif %}
+                       
+            {% if not request.user.is_authenticated %}                                                                        
+            <input name="ask" type="button" value="{% trans "Login/signup to post your question" %}" class="submit" onclick="submitClicked(event, this.form)"/>
+                       {% else %}
+            <input name="ask" type="button" value="{% trans "Ask your question" %}" class="submit" onclick="submitClicked(event, this.form)"/>
+            {% endif %}
+        </form>
+    </div>
+</div>
+{% endblock %}
+
+{% block sidebar %}
+{% include "question_edit_tips.html" %}
+{% endblock %}
+
+{% block endjs %}
+{% endblock %}
+<!-- end template ask.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/auth/auth_settings.html b/forum/modules/template_loader.py/forum/skins/default/templates/auth/auth_settings.html
new file mode 100644 (file)
index 0000000..8b52019
--- /dev/null
@@ -0,0 +1,38 @@
+{% extends "user.html" %}
+<!-- changepw.html -->
+{% load i18n %}
+{% block head %}{% endblock %}
+{% block title %}{% spaceless %}{% trans "Authentication settings" %}{% endspaceless %}{% endblock %}
+{% block usercontent %}
+<h2>{% trans "Authentication settings" %}</h2>
+{% if auth_keys %}
+    <p class="message">{% blocktrans %}These are the external authentication providers currently associated with your account.{% endblocktrans %}</p>
+    <div>
+        {% for key in auth_keys %}
+            <p>{{ key.name }} (<a href="{% url user_remove_external_provider id=key.id %}">{% trans "remove" %}</a>)</p>
+        {% endfor %}
+    </div>
+{% endif %}
+{% if not auth_keys %}
+    <p class="message">{% blocktrans %}You currently have no external authentication provider associated with your account.{% endblocktrans %}</p>
+{% endif %}
+{% ifequal view_user request.user %}
+    <input type="button" class="submit" value="{% trans "Add new provider" %}" onclick="window.location='{% url user_add_external_provider %}'" />
+{% endifequal %}
+{% if allow_local_auth %}
+{% if has_password %}
+    <p class="message">{% blocktrans %}This is where you can change your password. Make sure you remember it!{% endblocktrans %}</p>
+{% else %}
+    <p class="message">{% blocktrans %}You can set up a password for your account, so you can login using standard username and password!{% endblocktrans %}</p>
+{% endif %}
+<div class="aligned">
+       <form action="" method="post" accept-charset="utf-8">
+        <ul id="changepw-form" class="form-horizontal-rows">
+        {{form.as_ul}}
+        </ul>
+        <div class="submit-row"><input type="submit" class="submit" value="{% if has_password %}{% trans "Change password" %}{% endif %}{% if not has_password %}{% trans "Create password" %}{% endif %}" /></div>
+       </form>
+       </div>
+{% endif %}
+{% endblock %}
+<!-- end changepw.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/auth/complete.html b/forum/modules/template_loader.py/forum/skins/default/templates/auth/complete.html
new file mode 100644 (file)
index 0000000..c5a3c9e
--- /dev/null
@@ -0,0 +1,105 @@
+{% extends "base_content.html" %}
+<!-- complete.html -->
+{% load i18n %}
+{% block head %}{% endblock %}
+{% block title %}{% spaceless %}{% trans "Connect your OpenID with this site" %}{% endspaceless %}{% endblock %}
+{% block content %}
+    <div id="main-bar" class="headNormal">
+               {% trans "Connect your OpenID with your account on this site" %}
+    </div>      
+       <div id="completetxt" >
+        <div class="message">
+            <b>{% trans "You are here for the first time with " %}{{ provider }}</b>
+            {% trans "Please create your screen name and save your email address. Saved email address will let you subscribe for the updates on the most interesting questions and will be used to create and retrieve your unique avatar image. " %}
+        </div>
+       <p style="display:none">{% trans "This account already exists, please use another." %}</p>
+       </div>
+
+       {% if form1.errors %}
+        <ul class="errorlist">
+        {% if form1.non_field_errors %}
+            {% for error in form1.non_field_errors %}
+                <li>{{error}}</li>
+            {% endfor %}
+        {% endif %}
+        </ul>
+       {% endif %}
+
+       <div class="login">
+        <form name="fregister" action="" method="POST">
+            {{ form1.next }}
+            <div class="form-row-vertical margin-bottom">
+                <label for="id_username">{{ form1.username.label }}</label>
+                {% if form1.username.errors %} 
+                    <p class="error">{{ form1.username.errors|join:", " }}</p>
+                {% endif %}
+                {{ form1.username }}
+            </div>
+            <div class="form-row-vertical margin-bottom">
+                <label for="id_email">{{ form1.email.label }}</label>
+                {% if form1.email.errors %} 
+                    <p class="error">{{ form1.email.errors|join:", " }}</p>
+                {% endif %}
+                {{ form1.email }}
+            </div>
+            {% if form1.password1 %}
+                <div class="form-row-vertical margin-bottom">
+                    <label for="password1_id">{{ form1.password1.label }}</label>
+                    {% if form1.password1.errors %}
+                        <p class="error">{{ form1.password1.errors|join:", " }}</p>
+                    {% endif %}
+                    {{ form1.password1 }}
+                </div>
+                <div class="form-row-vertical margin-bottom">
+                    <label for="password2_id">{{ form1.password2.label }}</label>
+                    {% if form1.password2.errors %} 
+                        <p class="error">{{ form1.password2.errors|join:", " }}</p>
+                    {% endif %}
+                    {{ form1.password2 }}
+                </div>
+            {% endif %}
+            {% if form1.recaptcha %}
+                <div class="form-row-vertical margin-bottom">
+                <label for="recaptcha_id">{{ form1.recaptcha.label }}</label>
+                {% if form1.recaptcha.errors %} 
+                    <p class="error">{{ form1.recaptcha.errors|join:", " }}</p>
+                {% endif %}
+                {{ form1.recaptcha }}
+                </div>
+            {% endif %}
+            <p>{% trans "receive updates motivational blurb" %}</p>
+            <div class='simple-subscribe-options'>
+            {{email_feeds_form.subscribe}}
+            {% if email_feeds_form.errors %}
+            <p class="error">{% trans "please select one of the options above" %}</p>
+            {% endif %}
+            </div>
+            <p class='space-above'>{% trans "Tag filter tool will be your right panel, once you log in." %}</p>
+            <div class="submit-row"><input type="submit" class="submit" name="bnewaccount" id="bnewaccount" value="{% trans "create account" %}"/></div>
+               </form>
+       </div>
+    {% comment %}<!-- this form associates openID with an existing password-protected account, not yet functional -->
+    {% if form2 %}
+       <div class="login" style="display:none">
+        <form name="fverify" action="{% url user_register %}" method="POST">
+            {{ form2.next }}
+                       <fieldset style="padding:10px">
+                               <legend class="big">{% trans "Existing account" %}</legend>
+                               <div class="form-row"><label for="id_username">{% trans "user name" %}</label><br/>{{ form2.username }}</div>
+                               <div class="form-row"><label for="id_passwordl">{% trans "password" %}</label><br/>{{ form2.password }}</div>
+                <p><span class='big strong'>(Optional) receive updates by email</span> - only sent when there are any.</p>
+                <div class='simple-subscribe-options'>
+                {{email_feeds_form.subscribe}}
+                </div>
+                               <!--todo double check translation from chinese 确认 = "Register" -->
+                               <div class="submit-row">
+                                       <input type="submit" class="submit" name="bverify" value="{% trans "Register" %}"/> 
+                                       <a href="{% url user_sendpw %}">{% trans "Forgot your password?" %}</a>
+                               </div>
+                       </fieldset>
+               </form>
+       </div>
+    {% endif %}
+    {% endcomment %}
+{% endblock %}
+<!-- end complete.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/auth/mail_already_validated.html b/forum/modules/template_loader.py/forum/skins/default/templates/auth/mail_already_validated.html
new file mode 100644 (file)
index 0000000..dd37fa3
--- /dev/null
@@ -0,0 +1,17 @@
+{% extends "base_content.html" %}
+<!-- complete.html -->
+{% load i18n %}
+{% block head %}{% endblock %}
+{% block title %}{% spaceless %}{% trans "This e-mail has already been validated" %}{% endspaceless %}{% endblock %}
+{% block content %}
+
+<div class="error">
+
+<h1>{% blocktrans %}Already validated{% endblocktrans %}</h1>
+
+<p>{% blocktrans %}This e-mail has already been validated{% endblocktrans %}</p>
+
+</div>
+
+{% endblock %}
+<!-- end complete.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/auth/mail_validation.html b/forum/modules/template_loader.py/forum/skins/default/templates/auth/mail_validation.html
new file mode 100644 (file)
index 0000000..82029d6
--- /dev/null
@@ -0,0 +1,30 @@
+{% load i18n extra_tags email_tags %}
+
+{% declare %}
+    prefix = settings.EMAIL_SUBJECT_PREFIX
+    app_name = settings.APP_SHORT_NAME
+
+    exclude_finetune = True
+{% enddeclare %}
+
+{% email %}
+    {% subject %}{% blocktrans %}{{ prefix }} Your email validation link {{ app_name }}{% endblocktrans %}{% endsubject %}
+
+    {% htmlcontent notifications/base.html %}
+        <p style="{{ p_style }}">{% trans "Please use the following link to help us verify your email address:" %}</p>
+
+        <p style="{{ p_style }}"><a  style="{{ a_style }}" href="{% fullurl auth_validate_email user=recipient.id,code=validation_code %}">{% trans "Validate my email address" %}</a></p>
+
+        <p style="{{ p_style }}">{% trans "If the above link is not clickable, copy and paste this url into your web browser's address bar:" %}</p>
+
+        <p style="{{ p_style }}">{% fullurl auth_validate_email user=recipient.id,code=validation_code %}</p>
+    {% endhtmlcontent %}
+
+{% textcontent notifications/base_text.html %}
+{% trans "Copy and paste this url into your web browser's address bar to help us verify your email address:" %}
+
+{% fullurl auth_validate_email user=recipient.id,code=validation_code %}
+{% endtextcontent %}
+
+{% endemail %}
+
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/auth/signin.html b/forum/modules/template_loader.py/forum/skins/default/templates/auth/signin.html
new file mode 100644 (file)
index 0000000..19dee07
--- /dev/null
@@ -0,0 +1,184 @@
+{% extends "base.html" %}\r
+\r
+{% load i18n %}\r
+{% load extra_tags %}\r
+\r
+{% block title %}{% spaceless %}{% trans "Login" %}{% endspaceless %}{% endblock %}\r
+        \r
+{% block forejs %}\r
+    <link rel="stylesheet" type="text/css" media="screen" href="{% media "/media/style/auth.css" %}"/>\r
+    {% for provider in all_providers %}\r
+        {% for location in provider.extra_css %}\r
+            <link rel="stylesheet" type="text/css" media="screen" href="{{ location }}"/>\r
+        {% endfor %}\r
+    {% endfor %}\r
+{% endblock %}\r
+\r
+{% block content %}\r
+    {% for provider in all_providers %}\r
+        {% if provider.pre_code %}\r
+            {{ provider.pre_code|safe }}\r
+        {% endif %}\r
+    {% endfor %}\r
+    <div class="headNormal">\r
+           {% trans "User login" %}\r
+    </div>\r
+    {% if msg %}\r
+        <p class="error">{{ msg }}</p>\r
+    {% endif %}\r
+    {% for provider in top_stackitem_providers %}\r
+        <form class="signin_form" method="POST" action="{% url auth_provider_signin provider=provider.id %}" accept-charset="utf-8">\r
+            {% include provider.stack_item_template %}\r
+            <input type="hidden" class="validate_email" name="validate_email" value="yes" />\r
+        </form>\r
+    {% endfor %}\r
+    {% if top_stackitem_providers %}\r
+        <h3 class="or_label">{% trans 'Or...' %}</h3>\r
+    {% endif %}\r
+    <div style="width:600px;float:left;margin-bottom:5px;">\r
+    {% blocktrans %}\r
+        External login services use <b><a href="http://openid.net/">OpenID</a></b> technology, where your password always stays confidential between\r
+        you and your login provider and you don't have to remember another one.\r
+    {% endblocktrans %}\r
+    </div>\r
+    {% if request.user.is_anonymous %}\r
+        <div style="width:600px;float:left;margin-bottom:5px;">\r
+            <input type="checkbox" checked="checked" id="validate_email" />\r
+            {% trans "Validate my email after I login." %}\r
+        </div>\r
+    {% endif %}\r
+    <div id="bigicon_providers">\r
+        {% for provider in bigicon_providers %}\r
+            <div class="provider_logo big" name="{{ provider.id }}">\r
+                <div class="inner">\r
+                    {% ifequal provider.type "DIRECT" %}\r
+                        <a class="provider_direct" href="{% url auth_provider_signin provider=provider.id %}">\r
+                            <img src="{% media provider.icon %}" />\r
+                        </a>\r
+                    {% endifequal %}\r
+                    {% ifequal provider.type "CUSTOM" %}\r
+                        {% include provider.code_template %}\r
+                    {% endifequal %}\r
+                    {% ifequal provider.type "SIMPLE_FORM" %}\r
+                        <img alt="{{ provider.simple_form_context.your_what }}" class="simple_form_provider" src="{% media provider.icon %}" />\r
+                    {% endifequal %}\r
+                </div>\r
+            </div>\r
+        {% endfor %}\r
+    </div>\r
+    <div id="smallicon_providers">\r
+        {% for provider in smallicon_providers %}\r
+            <div class="provider_logo small" name="{{ provider.id }}">\r
+                <div class="inner">\r
+                    {% ifequal provider.type "DIRECT" %}\r
+                        <a class="provider_direct" href="{% url auth_provider_signin provider=provider.id %}">\r
+                            <img src="{% media provider.icon %}" />\r
+                        </a>\r
+                    {% endifequal %}\r
+                    {% ifequal provider.type "CUSTOM" %}\r
+                        {% include provider.code_template %}\r
+                    {% endifequal %}\r
+                    {% ifequal provider.type "SIMPLE_FORM" %}\r
+                        <img alt="{{ provider.simple_form_context.your_what }}" class="simple_form_provider" src="{% media provider.icon %}" />\r
+                    {% endifequal %}\r
+                </div>\r
+            </div>\r
+        {% endfor %}\r
+    </div>\r
+    <form name="signin_form" id="signin_form" class="signin_form" method="POST" action="">\r
+        <div id="signin_form_slot"></div>\r
+        <input type="hidden" class="validate_email" name="validate_email" value="yes" />\r
+    </form>\r
+    {% for provider in stackitem_providers %}\r
+        <h3 class="or_label">{% trans 'Or...' %}</h3>\r
+        <form class="signin_form" method="POST" action="{% url auth_provider_signin provider=provider.id %}" accept-charset="utf-8">\r
+            {% include provider.stack_item_template %}\r
+            <input type="hidden" class="validate_email" name="validate_email" value="yes" />\r
+        </form>\r
+    {% endfor %}\r
+    <h3 class="or_label">{% trans 'Or...' %}</h3>\r
+    <form name="signin_form" id="dummy_form_unused" class="signin_form" method="POST" action="">\r
+        <fieldset>\r
+            {% trans 'Click' %} <a href="{% url auth_request_tempsignin %}">{% trans 'here' %}</a> {% trans "if you're having trouble signing in." %}\r
+        </fieldset>\r
+    </form>\r
+    <script type="text/html" id="simple_form_template">\r
+        <fieldset id="slot_form">\r
+              <p id="provider_name_slot">{% trans 'Enter your ' %}%%YOUR_WHAT%%</p>\r
+              <div><p><span></span>\r
+                    <input id="input_field" type="text" name="input_field" /><span></span>\r
+                    <input id="ssignin" name="ssignin" type="submit" value="Login" />\r
+              </p></div>\r
+              <input type="hidden" class="validate_email" name="validate_email" value="yes" />\r
+          </fieldset>\r
+    </script>\r
+    <script type="text/javascript">\r
+        $(function() {\r
+            var signin_url = "{% url auth_provider_signin provider='PROVIDER' %}";\r
+\r
+            function set_validate_email() {\r
+                var validate = $('#validate_email').attr('checked') ? 'yes' : 'no';\r
+                $('.validate_email').attr('value', validate);\r
+\r
+                $('.provider_direct').each(function() {\r
+                    var current_url = $(this).attr('href');\r
+                    if (!/\?validate_email\=(yes|no)$/.test(current_url)) {\r
+                        current_url += ('?validate_email=' + validate);\r
+                    } else {\r
+                        current_url = current_url.replace(/(yes|no)$/, validate);\r
+                    }\r
+\r
+                    $(this).attr('href', current_url);\r
+                })\r
+            }\r
+\r
+            $('#validate_email').change(set_validate_email);\r
+\r
+            function set_form_action(el) {\r
+                var provider = el.parents('.provider_logo').attr('name');\r
+                $('#signin_form').attr('action', signin_url.replace('PROVIDER', provider));\r
+            }\r
+\r
+            $('.provider_logo').click(function() {\r
+                $('.provider_logo').removeClass('selected');\r
+                $(this).addClass('selected');\r
+            });\r
+\r
+            $('.simple_form_provider').click(function() {\r
+                $('#signin_form_slot').html('');\r
+                var new_html = $('#simple_form_template').html()\r
+                    .replace('%%YOUR_WHAT%%', $(this).attr('alt'));\r
+                $('#signin_form_slot').html(new_html);\r
+                set_form_action($(this));\r
+                set_validate_email();\r
+            })\r
+\r
+            set_validate_email();\r
+        });\r
+    </script>\r
+{% endblock %}\r
+\r
+{% block sidebar %}\r
+<div class="boxC">\r
+    <h3 class="subtitle">{% trans "Why use OpenID?" %}</h3>\r
+    <ul class="list-item">\r
+        <li>\r
+               {% trans "with openid it is easier" %}\r
+        </li>\r
+        <li>\r
+               {% trans "reuse openid" %}\r
+        </li>\r
+        <li>\r
+               {% trans "openid is widely adopted" %}\r
+        </li>\r
+        <li>\r
+               {% trans "openid is supported open standard" %}\r
+        </li>\r
+\r
+    </ul>\r
+    <p class="info-box-follow-up-links">\r
+        <a href="http://openid.net/what/" target="_blank">{% trans "Find out more" %} </a><br/>\r
+        <a href="http://openid.net/get/" target="_blank">{% trans "Get OpenID" %} </a>\r
+    </p>\r
+</div>\r
+{% endblock%}\r
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/auth/temp_login_email.html b/forum/modules/template_loader.py/forum/skins/default/templates/auth/temp_login_email.html
new file mode 100644 (file)
index 0000000..32ade89
--- /dev/null
@@ -0,0 +1,31 @@
+{% load i18n extra_tags email_tags %}
+
+{% declare %}
+    prefix = settings.EMAIL_SUBJECT_PREFIX
+    app_name = settings.APP_SHORT_NAME
+
+    exclude_finetune = True
+{% enddeclare %}
+
+{% email %}
+    {% subject %}{% blocktrans %}{{ prefix }} Temporary login link{% endblocktrans %}{% endsubject %}
+
+    {% htmlcontent notifications/base.html %}
+        <p style="{{ p_style }}">
+            {% blocktrans %}The following link grants you a one time access to your account at {{ app_name }}.{% endblocktrans %}
+        </p>
+        <p style="{{ p_style }}"><a  style="{{ a_style }}" href="{% fullurl auth_tempsignin user=recipient.id,code=temp_login_code %}">{% trans "Go to your account" %}</a></p>
+
+        <p style="{{ p_style }}">{% trans "If the above link is not clickable, copy and paste this url into your web browser's address bar:" %}</p>
+
+        <p style="{{ p_style }}">{% fullurl auth_tempsignin user=recipient.id,code=temp_login_code %}</p>
+    {% endhtmlcontent %}
+
+{% textcontent notifications/base_text.html %}
+{% blocktrans %}The following url grants you a one time access to your account at {{ app_name }}.{% endblocktrans %}
+
+{% fullurl auth_tempsignin user=recipient.id,code=temp_login_code %}
+{% endtextcontent %}
+
+{% endemail %}
+
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/auth/temp_login_request.html b/forum/modules/template_loader.py/forum/skins/default/templates/auth/temp_login_request.html
new file mode 100644 (file)
index 0000000..772f18f
--- /dev/null
@@ -0,0 +1,28 @@
+{% extends "base.html" %}\r
+\r
+{% load i18n %}\r
+{% block head %}{% endblock %}\r
+{% block title %}{% spaceless %}{% trans "Request temporary login key" %}{% endspaceless %}{% endblock %}\r
+{% block content %}\r
+<div class="headNormal">{% trans "Account: request temporary login key" %}</div>\r
+<p class="message">{% blocktrans %}\r
+    If you're experiencing problems accessing your account, or if you forgot your password,\r
+    here you can request a temporary login key. Fill out your account email and we'll send you a temporary access link that\r
+    will enable you to access your account. This token is valid only once and for a limited period of time.\r
+ {% endblocktrans %}</p>\r
+<div class="aligned">\r
+    {% if form.errors %}\r
+        <ul class="errorlist">\r
+            {% for error in form.errors %}\r
+                <li>{{ error }}</li>\r
+            {% endfor %}\r
+        </ul>\r
+       {% endif %}\r
+       <form action="" method="post" accept-charset="utf-8">\r
+        <ul id="changepw-form" class="form-horizontal-rows">\r
+        {{form.as_ul}}\r
+        </ul>\r
+        <div class="submit-row"><input type="submit" class="submit" value="{% trans "Send link" %}" /></div>\r
+       </form>\r
+       </div>\r
+{% endblock %}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/auth/welcome_email.html b/forum/modules/template_loader.py/forum/skins/default/templates/auth/welcome_email.html
new file mode 100644 (file)
index 0000000..1adcba2
--- /dev/null
@@ -0,0 +1,46 @@
+{% load i18n extra_tags email_tags %}
+
+{% declare %}
+    prefix = settings.EMAIL_SUBJECT_PREFIX
+    app_name = settings.APP_SHORT_NAME
+
+    exclude_greeting = True
+    exclude_finetune = True
+{% enddeclare %}
+
+{% email %}
+    {% subject %}{% blocktrans %}{{ prefix }} Welcome to {{ app_name }}{% endblocktrans %}{% endsubject %}
+
+    {% htmlcontent notifications/base.html %}
+        <p style="{{ p_style }}">
+            {% blocktrans %}Howdy and welcome to {{ app_name }}. We know you're busy, so we'll keep this real simple.{% endblocktrans %},
+        </p>
+
+        <p style="{{ p_style }}">{% trans "Here's your login info (store it in a cool dry place):" %}</p>
+
+        <p style="{{ p_style }}">{% trans "Username: " %} {{ recipient.username }}<br />
+        <b>{% trans "Password: As IF we would send your password in cleartext!" %}</b></p>
+
+        <p style="{{ p_style }}">{% trans "The following link will help us verify your email address:" %}</p>
+
+        <p style="{{ p_style }}"><a  style="{{ a_style }}" href="{% fullurl auth_validate_email user=recipient.id,code=validation_code %}">{% trans "Validate my email address" %}</a></p>
+
+        <p style="{{ p_style }}">{% trans "If the above link is not clickable, copy and paste this url into your web browser's address bar:" %}</p>
+
+        <p style="{{ p_style }}">{% fullurl auth_validate_email user=recipient.id,code=validation_code %}</p>
+    {% endhtmlcontent %}
+
+{% textcontent notifications/base_text.html %}
+{% blocktrans %}Howdy and welcome to {{ app_name }}. We know you're busy, so we'll keep this real simple.{% endblocktrans %},
+{% trans "Here's your login info (store it in a cool dry place):" %}
+
+{% trans "Username: " %} {{ recipient.username }}
+{% trans "Password: As IF we would send your password in cleartext!" %}
+
+{% trans "Copy and paste this url into your web browser's address bar to help us verify your email address:" %}
+
+{% fullurl auth_validate_email user=recipient.id,code=validation_code %}
+{% endtextcontent %}
+
+{% endemail %}
+
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/badge.html b/forum/modules/template_loader.py/forum/skins/default/templates/badge.html
new file mode 100644 (file)
index 0000000..341f239
--- /dev/null
@@ -0,0 +1,38 @@
+{% extends "base_content.html" %}
+<!-- template badge.html -->
+{% load i18n %}
+{% load extra_tags %}
+{% load user_tags %}
+{% load humanize %}
+{% block title %}{% spaceless %}{{ badge.name }} - {% trans "Badge" %}{% endspaceless %}{% endblock %}
+{% block forejs %}
+       <script type="text/javascript">
+        $().ready(function(){
+            $("#nav_badges").attr('className',"on");
+        });
+         
+        </script>
+{% endblock %}
+{% block content %}
+<div id="main-bar" class="headNormal">
+       {% trans "Badge" %}
+</div>
+<div id="main-body" style="width:100%;margin-bottom:20px">
+    <p>
+        <a href="{{badge.get_absolute_url}}" title="{{ badge.get_type_display }} : {{ badge.description }}" class="medal"><span class="badge{{ badge.type }}">&#9679;</span>&nbsp;{{ badge.name }}</a> {{ badge.description }}
+    </p>
+    <div>
+        {% if badge.awarded_count %}
+        <p style="float:left"><span class="count">{{ award_count|intcomma }}</span>
+        <strong>{% trans "The users have been awarded with badges:" %}</strong></p>
+        {% endif %}
+    </div>
+    <div id="award-list" style="clear:both;margin-left:20px;line-height:25px;">
+        {% for award in awards %}
+        <p style="width:220px;float:left">{% user_signature award.user "badges" %}<span class="tag-number"> &#215; {{ award.count|intcomma }}</span></p>
+        {% endfor %}
+    </div>
+
+</div>
+{% endblock %}
+<!-- end template badge.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/badges.html b/forum/modules/template_loader.py/forum/skins/default/templates/badges.html
new file mode 100644 (file)
index 0000000..aaac3ad
--- /dev/null
@@ -0,0 +1,67 @@
+{% extends "base.html" %}
+<!-- template badges.html -->
+{% load extra_tags %}
+{% load humanize %}
+{% load i18n %}
+{% block title %}{% spaceless %}{% trans "Badges summary" %}{% endspaceless %}{% endblock %}
+{% block content %}
+<div class="headlineA">
+        <span class="headMedals">{% trans "Badges" %}</span>
+</div>
+<div class="badges" id="main-body" style="width:100%">
+    <p>
+       {% trans "Community gives you awards for your questions, answers and votes." %}
+       {% blocktrans %}Below is the list of available badges and number of times each type of badge has been awarded.
+    {% endblocktrans %}
+    </p>
+    <div id="medalList">
+        {% for badge in badges %}
+        <div style="clear:both;line-height:30px">
+            <div style="float:left;min-width:30px;text-align:right;height:30px">
+            {% for a in mybadges %}
+                {% ifequal a.badge_id badge.id %}
+                 <span style="font-size:175%; padding-right:5px; color:#5B9058;">&#10004;</span>
+                {% endifequal %}
+            {% endfor %}
+            </div>
+            <div style="float:left;width:230px;">
+                <a href="{{badge.get_absolute_url}}" title="{{ badge.get_type_display }} : {{ badge.description }}" class="medal"><span class="badge{{ badge.type }}">&#9679;</span>&nbsp;{{ badge.name }}</a><strong> &#215; {{ badge.awarded_count|intcomma }}</strong>
+            </div>
+            <p style="float:left;margin-top:8px;">
+                {{ badge.description }}
+            </p>
+        </div>
+        {% endfor %}
+    </div>
+</div>
+{% endblock %}
+{% block sidebar %}
+
+<div class="boxC">
+    <h3>{% trans "Community badges" %}</h3>
+    <div class="body">
+    <p>
+        <a style="cursor:default;" title="{% trans "gold badge: the highest honor and is very rare" %}" class="medal"><span class="badge1">&#9679;</span>&nbsp;{% trans "gold" %}</a>
+    </p>
+    <p>
+       {% trans "gold badge description" %}
+    </p>
+    <p>
+        <a style="cursor:default;" 
+                       title="{% trans "silver badge: occasionally awarded for the very high quality contributions" %}" 
+                       class="medal"><span class="badge2">&#9679;</span>&nbsp;{% trans "silver" %}</a>
+    </p>
+    <p>
+       {% trans "silver badge description" %}
+    </p>
+    <p>
+        <a style="cursor:default;" title="{% trans "bronze badge: often given as a special honor" %}" class="medal">
+               <span class="badge3">&#9679;</span>&nbsp;{% trans "bronze" %}</a>
+    </p>
+    <p>
+       {% trans "bronze badge description" %}
+    </p>
+    </div>
+</div>
+{% endblock %}
+<!-- end template badges.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/base.html b/forum/modules/template_loader.py/forum/skins/default/templates/base.html
new file mode 100644 (file)
index 0000000..141dc39
--- /dev/null
@@ -0,0 +1,28 @@
+{% extends "base_content.html" %}
+{% block page_center %}
+
+{% block full_width_banner %}{% endblock %}
+
+<div id="wrapper">
+    {% block site_width_banner %}{% endblock %}
+    
+    <div id="room">
+        <div id="CALeft">
+            {% block content%}
+            {% endblock%}
+
+        </div>
+        <div id="CARight">
+            {% block sidebar%}
+            {% endblock%}
+
+        </div>
+        <div id="tail" style="clear:both;">
+            {% block tail %}
+            {% endblock %}
+        </div>
+    </div>
+    <div class="spacer3"></div>
+</div>
+{% endblock %}
+
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/base_content.html b/forum/modules/template_loader.py/forum/skins/default/templates/base_content.html
new file mode 100644 (file)
index 0000000..2281f0e
--- /dev/null
@@ -0,0 +1,138 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!-- base_content.html -->
+{% load i18n extra_tags extra_filters markup ui_registry %}
+<html xmlns="http://www.w3.org/1999/xhtml">
+    <head>
+        <title>{% block fulltitle %}{% block title %}{% endblock %} - {{ settings.APP_SHORT_NAME }}{% endblock %}</title>
+        <meta name="description" content="{% block metadescription %}{{ settings.APP_DESCRIPTION }}{% endblock %}">
+        <meta name="keywords" content="{% block metakeywords %}{{ settings.APP_KEYWORDS }}{% endblock %}">
+        {% block meta %}{% endblock %}
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+        {% if settings.GOOGLE_SITEMAP_CODE %}
+        <meta name="google-site-verification" content="{{ settings.GOOGLE_SITEMAP_CODE }}" />
+        {% endif %}
+        <link rel="shortcut icon" href="{{ settings.APP_FAVICON }}" />
+        <link href="{% media  "/media/style/style.css" %}" rel="stylesheet" type="text/css" />
+        {% if settings.USE_CUSTOM_CSS|or_preview:request %}
+        <link href="{% url custom_css %}" rel="stylesheet" type="text/css" />
+        {% endif %}
+        {% block forestyle %}{% endblock %}
+        <script src="http://www.google.com/jsapi" type="text/javascript"></script>
+        <script type="text/javascript">google.load("jquery", "1.4.2");</script>
+        <script type="text/javascript">
+        /* <![CDATA[ */
+            var i18nLang = '{{settings.LANGUAGE_CODE}}';
+            var scriptUrl = '{{settings.FORCE_SCRIPT_NAME}}/'
+            var osqaSkin = '{{settings.OSQA_SKIN}}';
+
+            var messages = {
+                username: '{{ user.username }}',
+                confirm: "{% trans "Are you sure?" %}",
+                yes: "{% trans "Yes" %}",
+                no: "{% trans "No" %}",
+                message: "{% trans "Message:" %}",
+                cancel: "{% trans "Cancel" %}",
+                close: "{% trans "Close" %}",
+                ok: "{% trans "Ok" %}",
+                matching_tags_url: "{% url matching_tags %}",
+                word: "{% trans "word" %}",
+                words: "{% trans "words" %}",
+                character: "{% trans "character" %}",
+                characters: "{% trans "characters" %}"
+            }
+        /* ]] */
+        </script>
+        <script type='text/javascript' src='{% media  "/media/js/osqa.main.js" %}'></script>
+        {% if user_messages %}
+        <style type="text/css">
+            body { margin-top:2.4em; }
+        </style>
+        <script type="text/javascript">
+            $(document).ready(function() {
+                var element = $('#validate_email_alert');
+                element.click(function(){notify.close(true);})
+                notify.show();
+            });
+        </script>
+        {% endif %}
+        {% if settings.USE_CUSTOM_HEAD|or_preview:request %}
+            {{ settings.CUSTOM_HEAD|or_preview:request|safe }}
+        {% endif %}
+        {% block forejs %}{% endblock %}
+        <link rel="search" type="application/opensearchdescription+xml" href="{% url opensearch %}" title="{{ settings.APP_SHORT_NAME }} Search" />
+        {% loadregistry head_content %}{% endloadregistry %}
+    </head>
+    <body>
+        <div class="notify" style="display:none">
+            {% autoescape off %}
+                {% if user_messages %}
+                    {% for message in user_messages %}
+                          <p class="darkred">{{ message }}</p>
+                    {% endfor %}
+                {% endif %}
+            {% endautoescape %}
+            <a id="close-notify" onclick="notify.close(true)">&times;</a>
+        </div>
+        {% if settings.USE_CUSTOM_HEADER|or_preview:request %}
+            <div id="custom_header">
+                {{ settings.CUSTOM_HEADER|or_preview:request|static_content:settings.CUSTOM_HEADER_RENDER_MODE }}
+            </div>
+        {% endif %}
+        {% include "header.html" %}
+        {% block page_center %}
+        <div id="wrapper">
+            <div id="room">
+                <div id="CAFull">
+                    {% block content%}
+                    {% endblock%}
+
+                </div>
+                <div id="tail" style="clear:both;">
+                    {% block tail %}
+                    {% endblock %}
+                </div>
+            </div>
+            <div class="spacer3"></div>
+        </div>
+        {% endblock %}
+        {% if settings.USE_CUSTOM_FOOTER|or_preview:request %}
+            {% ifequal settings.CUSTOM_FOOTER_MODE|or_preview:request "above" %}
+                <div id="custom_footer">
+                    {{ settings.CUSTOM_FOOTER|or_preview:request|static_content:settings.CUSTOM_FOOTER_RENDER_MODE }}
+                </div>
+            {% endifequal %}
+            <div id="ground">
+                {% ifequal settings.CUSTOM_FOOTER_MODE|or_preview:request "replace" %}
+                    {{ settings.CUSTOM_FOOTER|or_preview:request|static_content:settings.CUSTOM_FOOTER_RENDER_MODE }}
+                {% else %}
+                    {% include "footer.html" %}
+                {% endifequal %}
+            </div>
+            {% ifequal settings.CUSTOM_FOOTER_MODE|or_preview:request "below" %}
+                <div id="custom_footer">
+                    {{ settings.CUSTOM_FOOTER|or_preview:request|static_content:settings.CUSTOM_FOOTER_RENDER_MODE }}
+                </div>
+            {% endifequal %}
+        {% else %}
+            <div id="ground">
+                {% include "footer.html" %}
+            </div>
+        {% endif %}
+        {% block endjs %}
+        {% endblock %}
+        {% if settings.GOOGLE_ANALYTICS_KEY %}
+            <script type="text/javascript">
+                var _gaq = _gaq || [];
+                _gaq.push(['_setAccount', '{{ settings.GOOGLE_ANALYTICS_KEY }}']);
+                _gaq.push(['_trackPageview']);
+
+                (function() {
+                    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+                    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+                    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+                })();
+            </script>
+        {% endif %}
+    </body>
+</html>
+<!-- end template base_content.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/close.html b/forum/modules/template_loader.py/forum/skins/default/templates/close.html
new file mode 100644 (file)
index 0000000..d9e7350
--- /dev/null
@@ -0,0 +1,36 @@
+{% extends "base_content.html" %}
+<!-- template close.html -->
+{% load i18n %}
+{% load extra_tags %}
+{% load humanize %}
+{% block title %}{% spaceless %}{% trans "Close question" %}{% endspaceless %}{% endblock %}
+{% block forejs %}
+       <script type="text/javascript">
+        $().ready(function(){
+            $('#btBack').bind('click', function(){ history.back(); });
+        });
+        </script>
+{% endblock %}
+{% block content %}
+<div id="main-bar" class="headNormal">
+       {% trans "Close question" %}
+</div>
+<div id="main-body" style="width:100%;margin-bottom:10px">
+    <p>{% trans "Close the question" %}: <a href="{{ question.get_absolute_url }}">
+    <strong>{{ question.get_question_title }}</strong></a>
+    </p>   
+    
+    <form id="fmclose" action="{% url close question.id %}" method="post" >
+        <p>
+            <strong>{% trans "Reasons" %}:</strong> {{ form.reason }}
+        </p>
+        <div id="" style="padding-top:20px">
+            <input type="submit" value="{% trans "OK to close" %}" class="submit" />
+            <input id="btBack" type="button" class="submit" value="{% trans "Cancel" %}"  />
+            
+        </div>
+        
+    </form>
+</div>
+{% endblock %}
+<!-- end template close.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/edit_user_email_feeds_form.html b/forum/modules/template_loader.py/forum/skins/default/templates/edit_user_email_feeds_form.html
new file mode 100644 (file)
index 0000000..65902e7
--- /dev/null
@@ -0,0 +1,4 @@
+{% load i18n %}
+<table class='form-as-table'>
+{{email_feeds_form.as_table}}
+</table>
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/email_base.html b/forum/modules/template_loader.py/forum/skins/default/templates/email_base.html
new file mode 100644 (file)
index 0000000..211b394
--- /dev/null
@@ -0,0 +1,47 @@
+{% load extra_filters %}
+{% load extra_tags %}
+{% load email_tags %}
+{% load i18n %}
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+    <head>
+        <style type="text/css">
+            body {
+                background: #FFF;
+                font-size: 12px;
+                line-height: 150%;
+                margin: 0;
+                padding: 0;
+                color: #000;
+                font-family: sans-serif;
+            }
+
+            #wrapper {
+                width: 600px;
+                margin: auto;
+                padding: 0;
+            }
+
+            a img {
+                border: none;
+            }
+        </style>
+    </head>
+    <body>
+        <a href="{% fullurl index %}">
+            <img src="cid:logo" title="{% trans "home" %}" alt="{{settings.APP_TITLE}} logo"/>
+        </a>
+        <br />
+        <p>{{ settings.APP_TITLE }}</p>
+    <br /><br />
+    <div id="wrapper">
+            <div id="room">
+                <div id="CALeft">
+                    {% block content%}
+                    {% endblock%}
+                </div>
+            </div>
+            <div class="spacer3"></div>
+        </div>
+    </body>
+</html>
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/feedback.html b/forum/modules/template_loader.py/forum/skins/default/templates/feedback.html
new file mode 100644 (file)
index 0000000..38bb48f
--- /dev/null
@@ -0,0 +1,55 @@
+{% extends "base_content.html" %}
+<!-- template about.html -->
+{% load i18n %}
+{% load extra_tags %}
+{% load humanize %}
+{% block title %}{% spaceless %}{% trans "Feedback" %}{% endspaceless %}{% endblock %}
+{% block forejs %}
+{% endblock %}
+{% block content %}
+<div class="headNormal">
+{% trans "Give us your feedback!" %}
+</div>
+<div class="content">
+    <form method="post" action="{% url feedback %}" accept-charset="utf-8">
+        {% if user.is_authenticated %}
+            <p class="message">
+            {% blocktrans with user.username as user_name %}
+            <span class='big strong'>Dear {{user_name}}</span>, we look forward to hearing your feedback. 
+            Please type and send us your message below.
+            {% endblocktrans %}
+            <p>
+        {% else %}
+            <p class="message">
+            {% blocktrans %}
+            <span class='big strong'>Dear visitor</span>, we look forward to hearing your feedback.
+            Please type and send us your message below.
+            {% endblocktrans %}
+            </p>
+            <div class="form-row"><label>{{form.name.label}}</label><br/>{{form.name}}</div>
+            <div class="form-row">
+                <label>{{form.email.label}} 
+                    {% if form.errors.email %}
+                        <span class='red'>(please enter a valid email)</span>
+                    {% endif %}
+                </label><br/>{{form.email}}
+            </div>
+        {% endif %}
+        <div class="form-row">
+            <label>{{form.message.label}}
+            {% if form.errors.message %}
+            <span class="red">{% trans "(this field is required)" %}</span>
+            </label>
+            {% endif %}
+            <br/>
+            {{form.message}}
+        </div>
+        {{form.next}}
+        <div class="submit-row">
+            <input type="submit" class="submit" value="{% trans "Send Feedback" %}"/>
+            <input type="submit" class="submit" name="cancel" value="{% trans "Cancel" %}"/>
+        </div>
+    </form>
+</div>
+{% endblock %}
+<!-- end template about.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/feeds/rss_answer_title.html b/forum/modules/template_loader.py/forum/skins/default/templates/feeds/rss_answer_title.html
new file mode 100644 (file)
index 0000000..6b5d5ec
--- /dev/null
@@ -0,0 +1,2 @@
+{% load i18n %}
+{% blocktrans with obj.author.username as author %}Answer by {{ author }}{% endblocktrans %}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/feeds/rss_description.html b/forum/modules/template_loader.py/forum/skins/default/templates/feeds/rss_description.html
new file mode 100644 (file)
index 0000000..fa78190
--- /dev/null
@@ -0,0 +1 @@
+{{ obj.html|safe }}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/feeds/rss_title.html b/forum/modules/template_loader.py/forum/skins/default/templates/feeds/rss_title.html
new file mode 100644 (file)
index 0000000..be322ee
--- /dev/null
@@ -0,0 +1 @@
+{{ obj.title|safe }}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/footer.html b/forum/modules/template_loader.py/forum/skins/default/templates/footer.html
new file mode 100644 (file)
index 0000000..38a980f
--- /dev/null
@@ -0,0 +1,19 @@
+{% load extra_tags ui_registry i18n %}
+
+
+<div>
+    <div class="footerLinks" >
+        {% loadregistry footer_links %}<span class="link-separator"> |</span>{% endloadregistry %}
+    </div>
+  <p>
+     <a href="http://osqa.net" target="_blank" title="OSQA {{ settings.OSQA_VERSION }} ({{ settings.SVN_REVISION }})">
+        powered by OSQA
+     </a>
+  </p>
+</div>
+ <div id="licenseLogo">
+  <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">
+            <img src="{% media  "/media/images/by-sa-88x31.png" %}"" title="Creative Commons: Attribution - Share Alike" alt="cc-by-sa" width="88" height="31" />
+  </a>
+ </div>
+
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/header.html b/forum/modules/template_loader.py/forum/skins/default/templates/header.html
new file mode 100644 (file)
index 0000000..0e2d28c
--- /dev/null
@@ -0,0 +1,47 @@
+<!-- template header.html -->
+{% load extra_tags ui_registry i18n extra_filters markup %}
+
+       <div id="roof">
+         
+               <div id="logo">
+                       <a href="{% url index %}">
+                               <img src="{{ settings.APP_LOGO }}" title="{% trans "back to home page" %}" alt="{{settings.APP_TITLE}} logo"/>
+                       </a>
+               </div>
+         
+               <div id="top">
+                   {% loadregistry header_links %}{% endloadregistry %}
+               </div>
+
+    <div id="nav">
+        {% loopregistry page_top_tabs %}{% spaceless %}
+            <a id="nav_{{ tab_name }}"{% ifequal tab tab_name %} class="on"{% endifequal %} href="{{ tab_url }}" >{{ tab_title }}</a>
+        {% endspaceless %}{% endloopregistry %}
+        <a id="nav_ask" href="{% url ask %}" class="special">{% trans "ask a question" %}</a>
+    </div>
+  </div>
+
+  <div class="clear"></div>
+  
+       <div id="searchBar">
+    <form action="{% url search %}" method="get">
+        <div>
+            <input type="text" class="searchInput" value="{{ keywords }}" name="q" id="keywords" />
+            <input type="submit" name="Submit" value="{% trans "search" %}" class="searchBtn" />
+        </div>
+        <div class="options">
+            <input id="type-question" type="radio" value="question" name="t" 
+                checked="checked" /><label for="type-question">{% trans "questions" %}</label>
+            <input id="type-tag" type="radio" value="tag" name="t" /><label for="type-tag">{% trans "tags" %}</label>
+            <input id="type-user" type="radio" value="user" name="t" /><label for="type-user">{% trans "users" %}</label>
+        </div>
+    </form>    
+       </div>
+
+       {% if settings.USE_ANNOUNCEMENT_BAR|or_preview:request %}
+  <div id="announcement">
+      {{ settings.ANNOUNCEMENT_BAR|or_preview:request|static_content:settings.ANNOUNCEMENT_BAR_RENDER_MODE }}
+  </div>
+  {% endif %}
+
+<!-- end template header.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/index.html b/forum/modules/template_loader.py/forum/skins/default/templates/index.html
new file mode 100644 (file)
index 0000000..94552e6
--- /dev/null
@@ -0,0 +1,30 @@
+{% extends "questions.html" %}\r
+<!-- index.html -->\r
+{% load general_sidebar_tags %}\r
+{% load question_list_tags %}\r
+{% load i18n %}\r
+{% block fulltitle %}{{ settings.APP_TITLE }}{% endblock %}\r
+{% block sidebar %}\r
+    {% if not request.user.is_authenticated %}\r
+        {% if settings.SHOW_WELCOME_BOX %}\r
+            <div class="boxA">\r
+                <h3>{% trans "welcome to " %}{{ settings.APP_SHORT_NAME }}</h3>\r
+                <div class="body">\r
+                  {{ settings.APP_INTRO|safe }}\r
+                  <div class="more"><a href="{% url about %}">{% trans "about" %} </a></div>\r
+                  <div class="more"><a href="{% url faq %}">{% trans "faq" %} </a></div>\r
+                </div>\r
+            </div>\r
+        {% endif %}\r
+    {% endif %}\r
+    {% include "question_list/count.html" %}\r
+    {% sidebar_upper %}\r
+    {% if request.user.is_authenticated %}\r
+        {% tag_selector %}\r
+    {% endif %}\r
+    {% sidebar_lower %}\r
+    {% recent_tags %}\r
+    {% recent_awards %}\r
+{% endblock %}\r
+<!-- index.html -->\r
+\r
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/logout.html b/forum/modules/template_loader.py/forum/skins/default/templates/logout.html
new file mode 100644 (file)
index 0000000..650ba04
--- /dev/null
@@ -0,0 +1,23 @@
+{% extends "base_content.html" %}
+<!-- template logout.html -->
+{% load extra_tags %}
+{% load humanize %}
+{% load i18n %}
+{% block title %}{% spaceless %}{% trans "Logout" %}{% endspaceless %}{% endblock %}
+{% block forejs %}
+    <script type="text/javascript">
+    $().ready(function(){
+        $('#btLogout').bind('click', function(){ window.location.href='{% url user_signout %}?next={{ next }}'; });
+    });
+    </script>
+{% endblock %}
+{% block content %}
+<div  class="headNormal">
+    {% trans "Logout" %} 
+</div>
+<div id="main-body" style="width:100%">
+    <p>{% trans "As a registered user you can login with your OpenID, log out of the site or permanently remove your account." %}</p>
+    <input id="btLogout" type="button" class="submit" value="{% trans "Logout now" %}"><!-- style="width:150px">-->
+</div>
+{% endblock %}
+<!-- end logout.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/markdown_help.html b/forum/modules/template_loader.py/forum/skins/default/templates/markdown_help.html
new file mode 100644 (file)
index 0000000..78e11ce
--- /dev/null
@@ -0,0 +1,250 @@
+{% extends "base_content.html" %}
+{% load extra_tags %}
+{% load humanize %}
+{% load i18n %}
+
+{% block fulltitle %}{% spaceless %}{% trans "Markdown Help" %}{% endspaceless %}{% endblock %}
+
+{% block forejs %}
+    <link rel="stylesheet" type="text/css" media="all" href="{% media  "/media/style/markdown_help.css" %}" />
+{% endblock %}
+
+{% block content %}
+    <div id="main-wrapper"><br /><br />
+        <div id="heading">
+            <h1>{% trans "Markdown Syntax" %}</h1>
+            <p>{% blocktrans %}This document describes some of the more important parts of Markdown (for writers, that is).  There's a lot more to the syntax than is mentioned here, though.  To get the full syntax documentation, go to John Gruber's <a href="http://daringfireball.net/projects/markdown/syntax" rel="nofollow">Markdown Syntax</a> page{% endblocktrans %}</p>
+        </div>
+
+        <div class="section">
+            <h2 class="section-title">{% trans "Headers" %}</h2>
+            <div class="section-description">
+                {% trans "For top-level headers underline the text with equal signs.  For second-level headers use dashes to underline." %}
+            </div>
+            <table class="section-example"><tr>
+                <td>
+                    <code>{% trans "This is an H1" %}</code><br />
+                    <code>============= </code>
+                </td>
+                <td>
+                    <h1>{% trans "This is an H1" %}</h1>
+                </td>
+            </tr></table>
+            
+            <table class="section-example"><tr>
+                <td>
+                    <code>{% trans "This is an H2" %}</code><br />
+                    <code>-------------</code>
+                </td>
+                <td>
+                    <h2>{% trans "This is an H2" %}</h2>
+                </td>
+             </tr></table>
+
+            <div class="section-description">
+                {%  blocktrans %}If you would rather, you can prefix headers with a hash (#) symbol instead.  The number of hash symbols indicates the header level.  For example, a single hash indicates a header level of one while two indicates the second header level:{%  endblocktrans %}
+            </div>
+            <table class="section-example"><tr>
+                <td>
+                    <code># {% trans "This is an H1" %}</code>
+                </td>
+                <td>
+                    <h1>{% trans "This is an H1" %}</h1>
+                </td>
+            </tr></table>
+
+            <table class="section-example"><tr>
+                <td>
+                    <code>## {% trans "This is an H2" %}</code>
+                </td>
+                <td>
+                    <h2>{% trans "This is an H2" %}</h2>
+                </td>
+            </tr></table>
+
+            <table class="section-example"><tr>
+                <td>
+                    <code>### {% trans "This is an H3" %}</code>
+                </td>
+                <td>
+                    <h3>{% trans "This is an H3" %}</h3>
+                </td>
+             </tr></table>
+
+            <div class="section-description">
+                {% trans "Which you choose is a matter of style.  Whichever you thinks looks better in the text document.  In both cases, the final, fully formatted, document looks the same." %}
+            </div>
+        </div>
+
+        <div class="section">
+            <h2 class="section-title">{% trans "Paragraphs" %}</h2>
+            <div class="section-description">
+                {% trans "Paragraphs are surrounded by blank lines." %}
+            </div>
+            <div class="section-example">
+                <code>{% trans "This is paragraph one." %}</code>
+            </div><br />
+            <div class="section-example">
+                <code>{% trans "This is paragraph two." %}</code>
+            </div>
+        </div>
+
+        <div class="section">
+            <h2 class="section-title">{% trans "Links" %}</h2>
+            <div class="section-description">
+                {%  blocktrans %}
+                There are two parts to every link.
+                The first is the actual text that the user will see and it is surrounded by brackets.
+                The second is address of the page you wish to link to and it is surrounded in parenthesis.
+                {%  endblocktrans %}
+            </div>
+            <table class="section-example"><tr>
+                <td>
+                    <code>[{% trans "link text" %}]({% trans "http://example.com/" %})</code>
+                </td>
+                <td>
+                    <a>{% trans "link text" %}</a>
+                </td>
+            </tr></table>
+        </div>
+
+        <div class="section">
+            <h2 class="section-title">{% trans "Formatting" %}</h2>
+            <div class="section-description">
+                {% trans "To indicate bold text surround the text with two star (*) symbols or two underscore (_) symbols:" %}
+            </div>
+            <table class="section-example"><tr>
+                <td>
+                    <code>**{% trans "This is bold" %}**</code>
+                </td>
+                <td>
+                    <strong>{% trans "This is bold" %}</strong>
+                </td>
+            </tr></table>
+            <table class="section-example"><tr>
+                <td>
+                    <code>__{% trans "This is also bold" %}__</code>
+                 </td>
+                 <td>
+                     <strong>{% trans "This is also bold" %}</strong>
+                 </td>
+             </tr></table>
+
+            <div class="section-description">
+                {% trans "To indicate italicized text surround the text with a single star (*) symbol or underscore (_) symbol:" %}
+            </div>
+            <table class="section-example"><tr>
+                <td>
+                    <code>*{% trans "This is italics" %}*</code>
+                </td>
+                <td>
+                    <i>{% trans "This is italics" %}</i>
+                </td>
+            </tr></table>
+            <table class="section-example"><tr>
+                <td>
+                    <code>_{% trans "This is also italics" %}_</code>
+                 </td>
+                 <td>
+                     <i>{% trans "This is also italics" %}</i>
+                 </td>
+             </tr></table>
+
+            <div class="section-description">
+                {% trans "To indicate italicized and bold text surround the text with three star (*) symbol or underscore (_) symbol:" %}
+            </div>
+            <table class="section-example"><tr>
+                <td>
+                    <code>***{% trans "This is bold and italics" %}***</code>
+                </td>
+                <td>
+                    <strong><i>{% trans "This is bold and italics" %}</i></strong>
+                </td>
+            </tr></table>
+            <table class="section-example"><tr>
+                <td>
+                    <code>___{% trans "This is also bold and italics" %}___</code>
+                </td>
+                <td>
+                    <strong><i>{% trans "This is also bold and italics" %}</i></strong>
+                </td>
+            </tr></table>
+        </div>
+
+
+        <div class="section">
+            <h2 class="section-title">{% trans "Blockquotes" %}</h2>
+            <div class="section-description">
+                {% trans "To create an indented area use the right angle bracket (&gt;) character before each line to be included in the blockquote." %}
+            </div>
+            <table class="section-example"><tr>
+                <td>
+                    <code>&gt; {% trans "This is part of a blockquote." %}</code><br />
+                    <code>&gt; {% trans "This is part of the same blockquote." %}</code>
+                </td>
+                <td>
+                    <p style="padding-left:15px;">{% trans "This is part of a blockquote." %}<br />{% trans "This is part of the same blockquote." %}</p>
+                </td>
+            </tr></table>
+
+            <div class="section-description">
+                {% trans "Rather than putting it in front of each line to include in the block quote you can put it at the beginning and end the quote with a newline." %}
+            </div>
+            <table class="section-example"><tr>
+                <td>
+                    <code>&gt; {% trans "This is part of a blockquote." %}</code><br />
+                    <code>{% trans "This continues the blockquote even though there's no bracket." %}</code><br /><br />
+                    <code>{% trans "The blank line ends the blockquote." %}</code>
+                </td>
+                <td>
+                    <p style="padding-left:15px;">{% trans "This is part of a blockquote." %} <br /> {% trans "This continues the blockquote even though there's no bracket." %}</p>
+                    <p>{% trans "The blank line ends the blockquote." %}</p>
+                </td>
+            </tr></table>
+        </div>
+
+        <div class="section">
+             <h2 class="section-title">{% trans "Lists" %}</h2>
+             <div class="section-description">
+                 {% trans "To create a numbered list in Markdown, prefix each item in the list with a number followed by a period and space.  The number you use actually doesn't matter." %}
+             </div>
+             <table class="section-example"><tr>
+                 <td>
+                    <code>1. {% trans "Item" %} 1</code><br />
+                    <code>2. {% trans "Item" %} 2</code><br />
+                    <code>3. {% trans "Item" %} 3</code>
+                 </td>
+                 <td>
+                    <ol>
+                        <li>{% trans "Item" %} 1</li>
+                        <li>{% trans "Item" %} 2</li>
+                        <li>{% trans "Item" %} 3</li>
+                    </ol>
+                 </td>
+             </tr></table>
+
+             <div class="section-description">
+                 {% trans "To create a bulleted list, prefix each item in the list with a star (*) character." %}
+             </div>
+             <table class="section-example"><tr>
+                 <td>
+                    <code>* {% trans "A list item" %}</code><br />
+                    <code>* {% trans "Another list item" %}</code><br />
+                    <code>* {% trans "A third list item" %}</code>
+                 </td>
+                 <td>
+                    <ul>
+                        <li>{% trans "A list item" %}</li>
+                        <li>{% trans "Another list item" %}</li>
+                        <li>{% trans "A third list item" %}</li>
+                    </ul>
+                 </td>
+             </tr></table>
+        </div>
+
+        <div class="section">
+            <h2 class="section-title">{% trans "A Lot More" %}</h2>
+            <div class="section-description">{% blocktrans %}There's a lot more to the Markdown syntax than is mentioned here.  But for creative writers, this covers a lot of the necessities.  To find out more about Markdown than you'd ever want to really know, <a href="http://daringfireball.net/projects/markdown/syntax" target="_blank" rel="nofollow">go to the Markdown page where it all started</a>.{% endblocktrans %}</div>
+        </div>
+    </div>
+{% endblock %}
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/node/accept_button.html b/forum/modules/template_loader.py/forum/skins/default/templates/node/accept_button.html
new file mode 100644 (file)
index 0000000..653f8b1
--- /dev/null
@@ -0,0 +1,22 @@
+{% load i18n %}\r
+\r
+{% if can_accept %}\r
+    <a id="accept-answer-{{ answer.id }}" class="ajax-command accept-answer{% if answer.nis.accepted %} on{% endif %}"\r
+      title=" {% if answer.nis.accepted %}\r
+              {% blocktrans with answer.nstate.accepted.by.username as who %}{{ who }} has selected this answer as the correct answer{% endblocktrans %}\r
+              {% else %}\r
+                {% trans "mark this answer as the accepted answer" %}\r
+              {% endif %}"\r
+              bn:on="{% blocktrans with answer.nstate.accepted.by.username as who %}{{ who }} has selected this answer as the correct answer{% endblocktrans %}"\r
+              bn:off="{% trans "mark this answer as the accepted answer" %}"\r
+       href="{% url accept_answer id=answer.id %}" rel="nofollow"> \r
+    </a>\r
+{% else %}\r
+    {% if answer.nis.accepted %}\r
+      <a class="accept-answer on"\r
+        title="{% blocktrans with answer.nstate.accepted.by.username as who %}{{ who }} has selected this answer as the correct answer{% endblocktrans %}"\r
+        href="{% url accept_answer id=answer.id %}" rel="nofollow"> \r
+      </a>\r
+    {% endif %}\r
+{% endif %}\r
+\r
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/node/comments.html b/forum/modules/template_loader.py/forum/skins/default/templates/node/comments.html
new file mode 100644 (file)
index 0000000..49d529a
--- /dev/null
@@ -0,0 +1,86 @@
+{% load extra_tags %}\r
+{% load i18n %}\r
+\r
+<div class="comments-container" id="comments-container-{{ post.id }}">\r
+    {% for comment in comments %}\r
+        <a name="{{ comment.id }}"></a>\r
+        <div class="comment{% if not comment.top_scorer %} not_top_scorer{% endif %}" id="comment-{{comment.id}}">\r
+            <div id="post-{{ comment.id }}-score" class="comment-score">{% if comment.score %}{{ comment.score }}{% endif %}</div>\r
+            <div class="comment-text">{{ comment.comment }}</div>\r
+            <div class="comment-info" id="comment-{{comment.id}}-info">\r
+                {% if comment.can_like %}\r
+                    <a id="post-{{ comment.id }}-upvote" href="{% url like_comment id=comment.id %}"\r
+                     title="{% trans "I like this comment (click again to cancel)" %}" class="ajax-command comment-like{% if comment.likes %} on{% endif %}"\r
+                    rel="nofollow"> </a>\r
+                {% endif %}\r
+                {% if comment.can_edit %}\r
+                    <a id="comment-{{ comment.id }}-edit" href="{% url node_markdown id=comment.id %}" title="{% trans "Edit comment" %}"\r
+                        class="comment-edit" rel="nofollow"> </a>\r
+                {% endif %}\r
+                {% if comment.can_delete %}\r
+                    <a id="comment-{{ comment.id }}-delete" href="{% url delete_comment id=comment.id %}" title="{% trans "Delete comment" %}"\r
+                        class="ajax-command comment-delete" rel="nofollow"> </a>\r
+                {% endif %}\r
+                {% if comment.can_convert %}\r
+                    <a rel="nofollow" id="comment-{{ comment.id }}-convert" href="{% url convert_comment id=comment.id %}" title="{% trans "Convert comment to answer" %}"\r
+                        class="ajax-command comment-convert confirm" rel="nofollow"> </a>\r
+                {% endif %}\r
+                    \r
+\r
+                <span class="comment-age">({% diff_date comment.added_at %})</span>\r
+                <a class="comment-user userinfo" href="{{comment.user.get_profile_url}}">{{comment.user.decorated_name}}</a>\r
+                {% if show_gravatar %}{% gravatar comment.user 18 %}{% endif %}\r
+            </div>\r
+        </div>\r
+    {% endfor %}\r
+</div>\r
+<div id="comment-tools-{{ post.id }}" class="comment-tools">\r
+    {% ifnotequal showing total %}\r
+        <span class="comments-showing">\r
+            {% blocktrans %}showing {{ showing }} of {{ total }}{% endblocktrans %}\r
+        </span>\r
+        <a href="#" class="show-all-comments-link">{% trans "show all" %}</a>\r
+    {% endifnotequal %}\r
+    {% if can_comment %}\r
+        <a href="#" class="add-comment-link">{% trans "add new comment" %}</a>\r
+    {% endif %}\r
+</div>\r
+<div id="comment-{{ post.id }}-form-container" class="comment-form-container">\r
+    {% if can_comment %}\r
+    <form id="comment-{{ post.id }}-form" method="post" action="{% url comment id=post.id %}" accept-charset="utf-8">\r
+        <div class="comment-form-widgets-container">\r
+            <textarea name="comment" class="commentBox"></textarea>\r
+            <div class="comment-form-buttons">\r
+                <span id="comment-{{ post.id }}-chars-left" class="comment-chars-left">\r
+                    <span class="comments-char-left-count">{{ min_length }}|{{ max_length }}</span>\r
+                    <span class="comments-chars-togo-msg">{% trans "characters needed" %}</span>\r
+                    <span class="comments-chars-left-msg">{% trans "characters left" %}</span>\r
+                </span>\r
+                <input type="submit" class="comment-submit" value="{% trans " comment" %}" />\r
+                <input type="submit" class="comment-cancel" value="{% trans " cancel" %}" />\r
+            </div>\r
+        </div>\r
+        <script type="text/html" class="new-comment-skeleton" id="new-comment-skeleton-{{ post.id }}">\r
+            <div class="comment{% if not comment.top_scorer %} not_top_scorer{% endif %}" id="comment-%ID%">\r
+                <div id="post-%ID%-score" class="comment-score"></div>\r
+                <div class="comment-text">%COMMENT%</div>\r
+                <div class="comment-info" id="comment-%ID%-info">\r
+                    <a id="comment-%ID%-edit" href="%EDIT_URL%"\r
+                        class="comment-edit" rel="nofollow"> </a>\r
+                    <a id="comment-%ID%-delete" href="%DELETE_URL%"\r
+                        class="ajax-command comment-delete" rel="nofollow"> </a>\r
+                    <a rel="nofollow" id="comment-%ID%-convert" href="%CONVERT_URL%" title="{% trans "Convert comment to answer" %}"\r
+                        class="ajax-command comment-convert confirm" rel="nofollow"> </a>\r
+\r
+                    <span class="comment-age">({% trans "just now" %})</span>\r
+                    <a class="comment-user" href="%PROFILE_URL%">%USERNAME%</a>\r
+                    {% if user.is_authenticated %}\r
+                        {% if show_gravatar %}{% gravatar user 18 %}{% endif %}\r
+                    {% endif %}\r
+                </div>\r
+             </div>\r
+        </script>\r
+    </form>\r
+    {% endif %}\r
+</div>\r
+    \r
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/node/contributors_info.html b/forum/modules/template_loader.py/forum/skins/default/templates/node/contributors_info.html
new file mode 100644 (file)
index 0000000..3ed461b
--- /dev/null
@@ -0,0 +1,25 @@
+{% load extra_tags %}
+<div class='post-update-info post-update-info-user'>
+    <p style="line-height:12px;">
+        {{ node_verb }}
+        <strong>{% diff_date node.added_at %}</strong>
+    </p>
+    {% gravatar node.author 32 %}
+    <p><a {% if node.author.is_suspended %}class="suspended-user" {% endif %}href="{{ node.author.get_profile_url }}">{{ node.author.decorated_name }}</a><br/>
+    {% get_score_badge node.author %}</p>
+</div>
+{% if node.last_edited %}
+    <div class='post-update-info post-update-info-edited'>
+        <p style="line-height:12px;">
+            <a href="{{ node.get_revisions_url }}">
+                {{ node.last_edited.verb }}
+                <strong>{% diff_date node.last_edited.at %}</strong>
+            </a>
+        </p>
+        {% ifnotequal node.author node.last_edited.by %}
+            {% gravatar node.last_edited.by 32 %}
+            <p><a {% if node.last_edited.by.is_suspended %}class="suspended-user" {% endif %}href="{{ node.last_edited.by.get_profile_url }}">{{ node.last_edited.by.decorated_name }}</a><br/>
+            {% get_score_badge node.last_edited.by %}</p>
+        {% endifnotequal %}
+    </div>
+{% endif %}
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/node/convert_to_comment.html b/forum/modules/template_loader.py/forum/skins/default/templates/node/convert_to_comment.html
new file mode 100644 (file)
index 0000000..cbaa4cd
--- /dev/null
@@ -0,0 +1,10 @@
+{% load i18n %}
+
+<div>
+    <p>{% trans "Place the comment under:" %}</p>
+    <select name="under">
+        {% for id, descr in nodes %}
+            <option value="{{ id }}">{{ descr }}</option>
+        {% endfor %}
+    </select>
+</div>                   
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/node/convert_to_question.html b/forum/modules/template_loader.py/forum/skins/default/templates/node/convert_to_question.html
new file mode 100644 (file)
index 0000000..84ea16b
--- /dev/null
@@ -0,0 +1,7 @@
+{% load i18n %}
+<div>
+    <p>{% trans "Title of the new question:" %}</p>
+
+    <input type="text" name="title" />
+</div>
+
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/node/favorite_mark.html b/forum/modules/template_loader.py/forum/skins/default/templates/node/favorite_mark.html
new file mode 100644 (file)
index 0000000..6cfaac9
--- /dev/null
@@ -0,0 +1,8 @@
+{% load i18n %}\r
+\r
+<a id="favorite-mark" title="{% trans "mark/unmark this question as favorite (click again to cancel)" %}"\r
+    class="ajax-command favorite-mark {% if favorited %} on{% endif %}"\r
+    href="{% url mark_favorite id=question.id %}" rel="nofollow"> </a>\r
+<div id="favorite-count" class="favorite-count">\r
+   {% if favorite_count %}{{ favorite_count }}{% endif %}\r
+</div>\r
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/node/flagged_item.html b/forum/modules/template_loader.py/forum/skins/default/templates/node/flagged_item.html
new file mode 100644 (file)
index 0000000..b22c48b
--- /dev/null
@@ -0,0 +1,6 @@
+{% load extra_tags %}
+<div class='post-update-info'>
+    {{ action.describe|safe }}
+    at
+    {{ action.action_date }}
+</div>
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/node/post_controls.html b/forum/modules/template_loader.py/forum/skins/default/templates/node/post_controls.html
new file mode 100644 (file)
index 0000000..bbe1e22
--- /dev/null
@@ -0,0 +1,22 @@
+{% load i18n %}\r
+{% spaceless %}\r
+{% for control in controls %}\r
+    <span class="action-link">\r
+        <a rel="nofollow" title="{{ control.title }}" class="{{ control.classes }}" href="{{ control.url }}">{{ control.text }}</a>\r
+    </span>\r
+    {% ifnotequal controls|last control %}\r
+        <span class="action-link-separator">|</span>\r
+    {% endifnotequal %}\r
+{% endfor %}\r
+{% if menu|length %}\r
+    <span class="action-link-separator">|</span>\r
+    <span id="node-{{ post.id }}-menu" class="context-menu">\r
+        <span id="node-{{ post.id }}-menu-trigger" class="action-link context-menu-trigger">{% trans "more" %} &#9660;</span>\r
+        <ul id="node-{{ post.id }}-menu-dropdown" class="context-menu-dropdown">\r
+            {% for item in menu %}\r
+            <li class="item"><a rel="nofollow" class="{{ item.classes }}" href="{{ item.url }}" title="{{ item.title }}" >{{ item.text }}</a></li>\r
+            {% endfor %}\r
+        </ul>\r
+    </span>\r
+{% endif %}\r
+{% endspaceless %}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/node/report.html b/forum/modules/template_loader.py/forum/skins/default/templates/node/report.html
new file mode 100644 (file)
index 0000000..1635d7d
--- /dev/null
@@ -0,0 +1,14 @@
+{% load i18n %}\r
+\r
+{% trans "Please select a reason bellow or use the text box to input your own reason." %}\r
+<select class="prompt-examples">\r
+    {% for type in types %}\r
+        <option value="{{ type }}">{{ type }}</option>\r
+    {% endfor %}\r
+</select>\r
+<textarea name="prompt">{{ types|first }}</textarea>\r
+<script>\r
+$('.prompt-examples').change(function() {\r
+    $('textarea[name=prompt]').val($(this).val())            \r
+})\r
+</script>
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/node/reviser_info.html b/forum/modules/template_loader.py/forum/skins/default/templates/node/reviser_info.html
new file mode 100644 (file)
index 0000000..8b46047
--- /dev/null
@@ -0,0 +1,9 @@
+{% load extra_tags %}\r
+<div class='post-update-info'>\r
+    <p style="line-height:12px;">\r
+        <strong>{% diff_date revision.revised_at %}</strong>\r
+    </p>\r
+    {% gravatar revision.author 32 %}\r
+    <p><a href="{{ revised_at.author.get_profile_url }}">{{ revision.author.username }}</a><br/>\r
+    {% get_score_badge revision.author %}</p>\r
+</div>
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/node/revision.html b/forum/modules/template_loader.py/forum/skins/default/templates/node/revision.html
new file mode 100644 (file)
index 0000000..d6ac677
--- /dev/null
@@ -0,0 +1,11 @@
+{% spaceless %}\r
+    {% if title %}<h1>{{ title }}</h1>{% endif %}\r
+    <div class="text">{{ html }}</div>\r
+    {% if tags %}\r
+        <div class="tags">\r
+            {% for tag in tags %}\r
+            <a class="post-tag tag-link-{{ tag }}">{{ tag }}</a>\r
+            {% endfor %}\r
+        </div>\r
+    {% endif %}\r
+{% endspaceless %}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/node/vote_buttons.html b/forum/modules/template_loader.py/forum/skins/default/templates/node/vote_buttons.html
new file mode 100644 (file)
index 0000000..9b95d60
--- /dev/null
@@ -0,0 +1,12 @@
+{% load i18n %}\r
+\r
+<a id="post-{{ post.id }}-upvote" title="{% trans "I like this post (click again to cancel)" %}"\r
+    class="ajax-command post-vote up {% ifequal user_vote "up" %} on{% endifequal %}"\r
+     href="{% url vote_post id=post.id,vote_type='up' %}" rel="nofollow"> </a>\r
+<div id="post-{{ post.id }}-score" class="post-score"\r
+    title="{% trans "current number of votes" %}">\r
+    {{ post.score }}\r
+</div>\r
+<a id="post-{{ post.id }}-downvote" title="{% trans "I dont like this post (click again to cancel)" %}"\r
+    class="ajax-command post-vote down{% ifequal user_vote "down" %} on{% endifequal %}"\r
+     href="{% url vote_post id=post.id,vote_type='down' %}" rel="nofollow"> </a>
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/node/wiki_symbol.html b/forum/modules/template_loader.py/forum/skins/default/templates/node/wiki_symbol.html
new file mode 100644 (file)
index 0000000..3146a97
--- /dev/null
@@ -0,0 +1,11 @@
+{% load i18n extra_tags %}
+{% spaceless %}
+{% if is_wiki %}
+    <div class="community-wiki">
+        {% blocktrans %}This {{ post_type }} is marked "community wiki".{% endblocktrans %}
+        {% if can_edit %}
+            <br />{% blocktrans %}Feel free to <a href="{{ edit_url }}">edit it</a>.{% endblocktrans %}
+        {% endif %}
+    </div>
+{% endif %}
+{% endspaceless %}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/notarobot.html b/forum/modules/template_loader.py/forum/skins/default/templates/notarobot.html
new file mode 100644 (file)
index 0000000..698c569
--- /dev/null
@@ -0,0 +1,15 @@
+{% extends "base_content.html" %}
+{% load i18n %}
+{% block title %}{% spaceless %}{% trans "Please prove that you are a Human Being" %}{% endspaceless %}{% endblock %}
+{% block content %}
+{% comment %} this form is set up to be used in wizards {% endcomment %}
+<form name="notarobot" action="." method="POST">
+    <div>
+    {{form}}
+    </div>
+    <input type="submit" value="{% trans "I am a Human Being" %}" class="submit" style="float:left"/>
+    <input type="hidden" name="{{ step_field }}" value="{{ step0 }}" />
+    {{ previous_fields|safe }}
+    </form>
+</form>
+{% endblock %}
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/notifications/answeraccepted.html b/forum/modules/template_loader.py/forum/skins/default/templates/notifications/answeraccepted.html
new file mode 100644 (file)
index 0000000..7658087
--- /dev/null
@@ -0,0 +1,33 @@
+{% load i18n extra_tags email_tags %}
+
+{% declare %}
+    prefix = html.mark_safe(settings.EMAIL_SUBJECT_PREFIX)
+    answer_author = html.mark_safe(answer.author.username)
+    question = answer.question
+    question_title = html.mark_safe(question.title)
+    accepted_by = html.mark_safe(answer.nstate.accepted.by.username)
+    accepted_by_link = html.objlink(answer.nstate.accepted.by, style=settings.EMAIL_ANCHOR_STYLE)
+    answer_author_link = html.objlink(answer.author, style=settings.EMAIL_ANCHOR_STYLE)
+    question_link = html.objlink(question, style=settings.EMAIL_ANCHOR_STYLE)
+{% enddeclare %}
+
+{% email %}
+    {% subject %}{% blocktrans %}{{ prefix }} An answer to: {{ question_title }} has been accepted{% endblocktrans %}{% endsubject %}
+
+    {% htmlcontent notifications/base.html %}
+        <p style="{{ p_style }}">
+            {% blocktrans %}
+            {{ accepted_by_link }} has just accepted {{ answer_author_link }}'s answer on his question
+            {{ question_link }}.
+            {% endblocktrans %}
+        </p>
+    {% endhtmlcontent %}
+
+{% textcontent notifications/base_text.html %}
+{% blocktrans %}
+{{ accepted_by }} has just accepted {{ answer_author }}'s answer on his question
+"{{ question_title }}".
+{% endblocktrans %}
+{% endtextcontent %}
+
+{% endemail %}
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/notifications/base.html b/forum/modules/template_loader.py/forum/skins/default/templates/notifications/base.html
new file mode 100644 (file)
index 0000000..ca1f5f6
--- /dev/null
@@ -0,0 +1,35 @@
+{% load extra_filters extra_tags i18n email_tags %}
+
+{% declare %}
+    p_style = settings.EMAIL_PARAGRAPH_STYLE
+    a_style = settings.EMAIL_ANCHOR_STYLE
+    hr_style = "color:#ccc;border:0;height:1px;background-color:#ccc;margin-bottom:20px;"
+    small_style = "color:#333333;font-family:'Lucida Grande', Trebuchet, Helvetica, sans-serif;font-size:12px;"
+    table_style = "border:20px %s solid;margin:10px auto 10px auto;width:750px;text-align:left;" % settings.EMAIL_BORDER_COLOR
+{% enddeclare %}
+<html>
+<head>
+<base href="{{ settings.APP_URL }}">
+</head>
+<body style="margin:0;">
+<center>
+<table style="{{ table_style }}">
+<tbody><tr><td style="padding:20px;">
+<a href="{{ settings.APP_URL }}" style="border: 0;"><img src="{{ settings.APP_URL }}{{ settings.APP_LOGO }}" alt="{{settings.APP_TITLE}}" border="0"/></a>
+<hr style="{{ hr_style }}" />
+{% if not exclude_greeting %}
+<p style="{{ p_style }}">{% trans "Hello" %} {{ recipient.username }},</p>
+{% endif %}
+{% block content %}{% endblock%}
+<p style="{{ p_style }}">{% trans "Thanks" %},<br />{{settings.APP_SHORT_NAME}}</p>
+{% if not exclude_finetune %}
+<p style="{{ p_style }}">{% trans "P.S. You can always fine-tune which notifications you receive" %}
+<a href="{{ settings.APP_URL }}{% url user_subscriptions id=recipient.id,slug=recipient.username|slugify %}" style="{{ a_style }}">{% trans "here" %}</a>.
+{% endif %}
+</p>
+<hr style="{{ hr_style }}" />
+<p style="{{ p_style }}"><small style="{{ small_style }}">{{ settings.EMAIL_FOOTER_TEXT }}</small></p>
+</td></tr></tbody></table>
+</center>
+</body>
+</html>
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/notifications/base_text.html b/forum/modules/template_loader.py/forum/skins/default/templates/notifications/base_text.html
new file mode 100644 (file)
index 0000000..ec8714e
--- /dev/null
@@ -0,0 +1,17 @@
+{% load extra_filters extra_tags i18n email_tags %}
+
+{% if not exclude_greeting %}
+{% trans "Hello" %} {{ recipient.username }},
+{% endif %}
+
+{% block content %}{% endblock%}
+
+{% trans "Thanks" %},
+{{settings.APP_SHORT_NAME}}
+
+{% if not exclude_finetune %}
+{% trans "P.S. You can always fine-tune which notifications you receive here:" %}
+{{ settings.APP_URL }}{% url user_subscriptions id=recipient.id,slug=recipient.username|slugify %}
+{% endif %}
+
+{{ settings.EMAIL_FOOTER_TEXT }}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/notifications/digest.html b/forum/modules/template_loader.py/forum/skins/default/templates/notifications/digest.html
new file mode 100644 (file)
index 0000000..5c57375
--- /dev/null
@@ -0,0 +1,98 @@
+{% load i18n extra_tags email_tags %}
+
+{% declare %}
+    prefix = html.mark_safe(settings.EMAIL_SUBJECT_PREFIX)
+    app_name = settings.APP_SHORT_NAME
+    app_url = settings.APP_URL
+
+    new_member_links = html.mark_safe(", ".join([html.objlink(u, style=settings.EMAIL_ANCHOR_STYLE) for u in new_members]))
+    new_question_count = digest.count
+
+{% enddeclare %}
+
+{% email %}
+    {% subject %}{% blocktrans %}{{ prefix }} Daily digest{% endblocktrans %}{% endsubject %}
+
+    {% htmlcontent notifications/base.html %}
+        <p style="{{ p_style }}">
+            {% blocktrans %}
+            This is a brief of what's going on the {{ app_name }} community since our last update.
+            {% endblocktrans %}
+        </p>                           
+
+        {% if new_member_count %}
+        <p style="{{ p_style }}">
+        {% if show_all_users %}
+        {% blocktrans %}
+            There are {{ new_member_count }} new members in the community. {{ new_member_links }} were the most active so far.
+        {% endblocktrans %}
+        {% else %}
+        {% blocktrans %}
+            {{ new_member_links }} have joined the {{ app_name }} community.
+        {% endblocktrans %}
+        {% endif %}
+        {% endif %}
+        </p>
+
+        {% if new_question_count %}
+
+        {% declare %}
+            new_questions_link = html.hyperlink(app_url + reverse('questions') + '?sort=' + _('latest'), _('new questions'), style=a_style)
+            user_questions = digest.get_for_user(recipient)
+            subscriptions_link = html.hyperlink(app_url + recipient.get_subscribed_url(), _('subscriptions'), style=a_style)
+        {% enddeclare %}
+
+        <p style="{{ p_style }}">
+            {% blocktrans %}
+            {{ new_question_count }} {{ new_questions_link }} were posted since our last update.
+            {% endblocktrans %}
+        </p>
+
+        {% if user_questions.interesting %}
+        <p style="{{ p_style }}">
+            {% trans "We think you might like the following questions:" %}
+        </p>
+        <ul>
+        {% for q in user_questions.interesting %}
+            <li>
+                <a style="{{ a_style }}" href="{{ app_url }}{{ q.get_absolute_url  }}">{{ q.title }}</a>
+            </li>
+        {% endfor %}
+        </ul>
+        {% endif %}
+
+        {% if user_questions.may_help %}
+        <p style="{{ p_style }}">
+            {% trans "These new questions didn't get many attention from the community, but we think you may be able to help:" %}
+        </p>
+        <ul>
+        {% for q in user_questions.may_help %}
+            <li>
+                <a style="{{ a_style }}" href="{{ app_url }}{{ q.get_absolute_url  }}">{{ q.title }}</a>
+            </li>
+        {% endfor %}
+        </ul>
+
+        {% if user_questions.subscriptions %}
+        <p style="{{ p_style }}">
+            {% blocktrans %}Meanwhile, some of your {{ subscriptions_link }} have new updates since you last visited them:{% endblocktrans %}
+        </p>
+        <ul>
+        {% for q in user_questions.subscriptions %}
+            <li>
+                <a style="{{ a_style }}" href="{{ app_url }}{{ q.get_absolute_url  }}">{{ q.title }}</a>
+            </li>
+        {% endfor %}
+        </ul>
+        {% endif %}
+        
+        {% endif %}
+
+        {% endif %}
+
+    {% endhtmlcontent %}
+
+    {% textcontent notifications/base_text.html %}
+
+    {% endtextcontent %}
+{% endemail %}
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/notifications/feedback.html b/forum/modules/template_loader.py/forum/skins/default/templates/notifications/feedback.html
new file mode 100644 (file)
index 0000000..52aa6ad
--- /dev/null
@@ -0,0 +1,37 @@
+{% load i18n extra_tags email_tags %}
+
+{% declare %}
+    prefix = html.mark_safe(settings.EMAIL_SUBJECT_PREFIX)
+    app_name = html.mark_safe(settings.APP_SHORT_NAME)
+
+    exclude_greeting = True
+    exclude_finetune = True
+{% enddeclare %}
+
+{% email %}
+    {% subject %}{% blocktrans %}{{ prefix }} Feedback message from {{ app_name }}{% endblocktrans %}{% endsubject %}
+
+    {% htmlcontent notifications/base.html %}
+        <p style="{{ p_style }}">
+            {% trans "Sender" %}:{% if name %}{{ name }}{% else %}{% trans "anonymous" %}{% endif %}<br />
+            {% trans "email" %}: {{ email }}
+            <br/>
+                ip: {{ ip }}
+        </p>
+
+        <blockquote>
+        {% trans "Message body:" %} {{ message }}
+        </blockquote>
+
+    {% endhtmlcontent %}
+
+{% textcontent notifications/base_text.html %}
+{% trans "Sender" %}: {% if name %}{{ name|safe }}{% else %}{% trans "anonymous" %}{% endif %}
+{% trans "email" %}: {{ email|safe }}
+ip: {{ ip }}
+
+{% trans "Message body:" %} {{ message|safe }}
+{% endtextcontent %}
+
+{% endemail %}
+
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/notifications/newanswer.html b/forum/modules/template_loader.py/forum/skins/default/templates/notifications/newanswer.html
new file mode 100644 (file)
index 0000000..e9bbaaa
--- /dev/null
@@ -0,0 +1,44 @@
+{% load i18n extra_tags email_tags %}
+
+{% declare %}
+    prefix = html.mark_safe(settings.EMAIL_SUBJECT_PREFIX)
+    app_name = settings.APP_SHORT_NAME
+    safe_app_name = html.mark_safe(settings.APP_SHORT_NAME)
+    answer_author = html.mark_safe(answer.author.username)
+    question = answer.question
+    question_title = html.mark_safe(question.title)
+    safe_body = html.html2text(answer.html)
+    author_link = html.objlink(answer.author, style=settings.EMAIL_ANCHOR_STYLE)
+    question_link = html.objlink(question, style=settings.EMAIL_ANCHOR_STYLE)
+{% enddeclare %}
+
+{% email %}
+    {% subject %}{% blocktrans %}{{ prefix }} New answer to: {{ question_title }}{% endblocktrans %}{% endsubject %}
+
+    {% htmlcontent notifications/base.html %}
+        <p style="{{ p_style }}">
+            {% blocktrans %}
+            {{ author_link }} has just posted a new answer on {{ app_name }} to the question
+            {{ question_link }}:
+            {% endblocktrans %}
+        </p>
+
+        <blockquote>
+        {{ answer.html|safe }}
+        </blockquote>
+
+        <p style="{{ p_style }}">{% trans "Don't forget to come over and cast your vote." %}</p>
+    {% endhtmlcontent %}
+
+{% textcontent notifications/base_text.html %}
+{% blocktrans %}
+{{ answer_author }} has just posted a new answer on {{ safe_app_name }} to the question
+"{{ question_title }}":
+{% endblocktrans %}
+{{ safe_body }}
+
+{% trans "Don't forget to come over and cast your vote." %}
+{% endtextcontent %}
+
+{% endemail %}
+
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/notifications/newcomment.html b/forum/modules/template_loader.py/forum/skins/default/templates/notifications/newcomment.html
new file mode 100644 (file)
index 0000000..9963a46
--- /dev/null
@@ -0,0 +1,46 @@
+{% load i18n extra_tags email_tags %}
+
+{% declare %}
+    prefix = html.mark_safe(settings.EMAIL_SUBJECT_PREFIX)
+    post = comment.parent
+    question = post.question and post.question or post
+    post_author = post.author.username
+    safe_post_author = html.mark_safe(post.author.username)
+    comment_author = html.mark_safe(comment.author)
+    question_title = html.mark_safe(question.title)
+    safe_body = html.html2text(comment.comment)
+    author_link = html.objlink(comment.author, style=settings.EMAIL_ANCHOR_STYLE)
+    question_link = html.objlink(question, style=settings.EMAIL_ANCHOR_STYLE)
+{% enddeclare %}
+
+{% email %}
+    {% subject %}{% blocktrans %}{{ prefix }} New comment on: {{ question_title }}{% endblocktrans %}{% endsubject %}
+
+    {% htmlcontent notifications/base.html %}
+        <p style="{{ p_style }}">
+            {% blocktrans %}{{ author_link }} has just posted a comment on {% endblocktrans %}
+            {% ifnotequal post question %}
+                {% blocktrans %}the answer posted by {{ post_author }} to {% endblocktrans %}
+            {% endifnotequal %}
+            {% blocktrans %}the question {{ question_link }}{% endblocktrans %}
+        </p>
+
+        <blockquote>
+        {{ comment.comment }}
+        </blockquote>
+
+        <p style="{{ p_style }}">{% trans "Don't forget to come over and cast your vote." %}</p>
+    {% endhtmlcontent %}
+
+{% textcontent notifications/base_text.html %}
+{% blocktrans %}{{ comment_author }} has just posted a comment on {% endblocktrans %}
+{% ifnotequal post question %}
+{% blocktrans %}the answer posted by {{ safe_post_author }} to {% endblocktrans %}
+{% endifnotequal %}
+{% blocktrans %}the question "{{ question_title }}"{% endblocktrans %}
+{{ safe_body }}
+
+{% trans "Don't forget to come over and cast your vote." %}
+{% endtextcontent %}
+
+{% endemail %}
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/notifications/newmember.html b/forum/modules/template_loader.py/forum/skins/default/templates/notifications/newmember.html
new file mode 100644 (file)
index 0000000..8efbe72
--- /dev/null
@@ -0,0 +1,34 @@
+{% load i18n extra_tags email_tags %}
+
+{% declare %}
+    prefix = html.mark_safe(settings.EMAIL_SUBJECT_PREFIX)
+    app_name = settings.APP_SHORT_NAME
+    safe_app_name = html.mark_safe(settings.APP_SHORT_NAME)
+    app_url = settings.APP_URL
+    newmember_name = newmember.username
+    safe_newmember_name = html.mark_safe(newmember.username)
+    newmember_url = newmember.get_profile_url()
+    newmember_link = html.objlink(newmember, style=settings.EMAIL_ANCHOR_STYLE)
+{% enddeclare %}
+
+{% email %}
+    {% subject %}{% blocktrans %}{{ prefix }} {{ safe_newmember_name }} is a new member on {{ safe_app_name }}{% endblocktrans %}{% endsubject %}
+
+    {% htmlcontent notifications/base.html %}
+        <p style="{{ p_style }}">
+            {% blocktrans %}
+            {{ newmember_link }} has just joined {{ app_name }}.
+            View <a style="{{ a_style }}" href="{{ app_url }}{{ newmember_url }}">{{ newmember_name }}'s profile</a>.
+            {% endblocktrans %}
+        </p>
+    {% endhtmlcontent %}
+
+{% textcontent notifications/base_text.html %}
+{% blocktrans %}
+{{ safe_newmember_name }} has just joined {{ safe_app_name }}. You can visit {{ safe_newmember_name }}'s profile using the following url:
+{{ app_url }}{{ newmember_url }}
+{% endblocktrans %}
+{% endtextcontent %}
+
+{% endemail %}
+
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/notifications/newquestion.html b/forum/modules/template_loader.py/forum/skins/default/templates/notifications/newquestion.html
new file mode 100644 (file)
index 0000000..7068bbb
--- /dev/null
@@ -0,0 +1,47 @@
+{% load i18n extra_tags email_tags %}
+
+{% declare %}
+    prefix = html.mark_safe(settings.EMAIL_SUBJECT_PREFIX)
+    app_name = settings.APP_SHORT_NAME
+    safe_app_name = html.mark_safe(settings.APP_SHORT_NAME)
+    question_author = html.mark_safe(question.author.username)
+    question_url = settings.APP_URL + question.get_absolute_url()
+    question_title = html.mark_safe(question.title)
+    question_tags = html.mark_safe(question.tagnames)
+    safe_body = html.html2text(question.html)
+    author_link = html.objlink(question.author, style=settings.EMAIL_ANCHOR_STYLE)
+    question_link = html.objlink(question, style=settings.EMAIL_ANCHOR_STYLE)
+    tag_links = html.mark_safe(" ".join([html.objlink(t, style=settings.EMAIL_ANCHOR_STYLE) for t in question.tags.all()]))
+{% enddeclare %}
+
+{% email %}
+    {% subject %}{% blocktrans %}{{ prefix }} New question: {{ question_title }} on {{ safe_app_name }}{% endblocktrans %}{% endsubject %}
+
+    {% htmlcontent notifications/base.html %}
+        <p style="{{ p_style }}">
+            {% blocktrans %}
+            {{ author_link }} has just posted a new question on {{ app_name }}, entitled
+            {{ question_link }}
+             and tagged "<em>{{ tag_links }}</em>". Here's what it says:
+            {% endblocktrans %}
+        </p>
+
+        <blockquote>
+            {{ question.html|safe }}
+        </blockquote>
+
+        <p style="{{ p_style }}">{% trans "Don't forget to come over and cast your vote." %}</p>        
+    {% endhtmlcontent %}
+
+{% textcontent notifications/base_text.html %}
+{% blocktrans %}
+{{ question_author }} has just posted a new question on {{ safe_app_name }}, entitled
+"{{ question_title }}" and tagged {{ question_tags }}:
+{% endblocktrans %}
+{{ safe_body }}
+
+{% trans "Don't forget to come over and cast your vote." %}
+{% endtextcontent %}
+
+{% endemail %}
+
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/opensearch.html b/forum/modules/template_loader.py/forum/skins/default/templates/opensearch.html
new file mode 100644 (file)
index 0000000..0c9d6bf
--- /dev/null
@@ -0,0 +1,8 @@
+{% load i18n %}
+<?xml version="1.0" encoding="UTF-8"?>
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
+   <ShortName>{{ settings.APP_SHORT_NAME }} {% trans "Search" %}</ShortName>
+   <Description>{% trans "Search" %} {{ settings.APP_SHORT_NAME }} {% trans "using your browser." %}</Description>
+   <Tags>{{ settings.APP_KEYWORDS }}</Tags>
+   <Url type="text/html" template="{{ settings.APP_URL }}/{% trans "search" %}/?q={searchTerms}&amp;t=question"/>
+</OpenSearchDescription>
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/base.html b/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/base.html
new file mode 100644 (file)
index 0000000..7f8a264
--- /dev/null
@@ -0,0 +1,51 @@
+{% extends "base.html" %}\r
+\r
+{% load i18n extra_tags general_sidebar_tags %}\r
+\r
+{% block forejs %}\r
+    <link rel="stylesheet" type="text/css" media="screen" href="{% media "/media/style/admin.css" %}"/>\r
+    <script type="text/javascript" src="{% media "/media/js/osqa.admin.js" %}"></script>\r
+    {% block adminjs %}{% endblock %}\r
+{% endblock %}\r
+\r
+{% block content %}\r
+    <div class="headNormal">\r
+           {% trans "OSQA administration area" %} - {% block subtitle %}{% endblock %}\r
+    </div>\r
+    <div id="admin_page_description">\r
+        {% block description %}{% endblock %}\r
+    </div>\r
+    <div>\r
+        {% block admincontent %}\r
+        {% endblock %}\r
+    </div>\r
+{% endblock %}\r
+\r
+{% block sidebar %}\r
+    <div class="boxC">\r
+        <a href="{% url admin_switch_interface %}?to=djstyle">{% trans "Switch to django style interface" %}</a>\r
+        <h3 class="subtitle">{% trans "Administration menu" %}</h3>\r
+        <ul>\r
+        {% for set in allsets.values %}\r
+            <li><a href="{% url admin_set set.name %}">{{ set.title }}</a></li>\r
+        {% endfor %}\r
+        \r
+        {% for set in othersets %}\r
+            <li>\r
+                <a href="{% url admin_set set.name %}">{{ set.title }}</a>\r
+            </li>\r
+        {% endfor %}\r
+        \r
+        <li><a href="{% url admin_maintenance %}">{% trans "Maintenance mode" %}</a></li>\r
+        <li><a href="{% url admin_flagged_posts %}">{% trans "Flagged Posts" %}</a></li>\r
+        {% for name,tool in tools.items %}\r
+            <li><a href="{% url admin_tools name %}">{{ tool.label }}</a></li>\r
+        {% endfor %}\r
+        </ul>\r
+    </div>\r
+    {% if markdown %}\r
+        {% markdown_help %}\r
+    {% endif %}\r
+{% endblock %}\r
+\r
+                \r
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/createuser.html b/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/createuser.html
new file mode 100644 (file)
index 0000000..4b0ed8c
--- /dev/null
@@ -0,0 +1,20 @@
+{% extends basetemplate %}
+
+{% load i18n %}
+{% load user_tags %}
+
+{% block subtitle %}
+    {% trans "Create User" %}
+{% endblock %}
+{% block description %}
+    {% trans "Quick creation of a new user" %}
+{% endblock %}
+
+{% block admincontent %}
+    <form action="" method="POST">
+        <table>
+            {{ form.as_table }}
+            <tr><th></th><td><input type="submit" value="{% trans "Save" %}"></td></tr>
+        </table>
+    </form>
+{% endblock %}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/dashboard.html b/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/dashboard.html
new file mode 100644 (file)
index 0000000..ec56e78
--- /dev/null
@@ -0,0 +1,81 @@
+{% extends basetemplate %}
+
+{% load i18n %}
+{% load user_tags %}
+
+{% block subtitle %}
+    {% trans "Dashboard" %}
+{% endblock %}
+{% block description %}
+    {% trans "Welcome to the OSQA administration area." %}
+{% endblock %}
+
+{% block admincontent %}
+    <div class="module" style="width:49%; display: inline-block; vertical-align: top;">
+        <table style="width: 100%; height: 100%;">
+            <caption>{% trans "Quick statistics"  %}</caption>
+            <tr>
+                <td>
+                {{ statistics.total_questions }} {% trans "question" %}{{ statistics.total_questions|pluralize }} ({{ statistics.questions_last_24 }} {% trans "in the last 24 hours" %})
+                </td>
+            </tr>
+            <tr>
+                <td>
+                {{ statistics.total_answers }} {% trans "answer" %}{{ statistics.total_answers|pluralize }} ({{ statistics.answers_last_24 }} {% trans "in the last 24 hours" %})
+                </td>
+            </tr>
+            <tr>
+                <td>
+                {{ statistics.total_users }} {% trans "user" %}{{ statistics.total_users|pluralize }} ({{ statistics.users_last_24 }} {% trans "joined in the last 24 hours" %})
+                </td>
+            </tr>
+        </table>
+    </div>
+    <div class="module" style="width:49%; display: inline-block;">
+        <table>
+        <caption>{%trans "Site status" %}</caption>
+            <tr>
+                <td>
+                    {% ifequal settings_pack "bootstrap" %}
+                        {% trans "Your site is running in bootstrap mode, click the button below to revert to defaults." %}<br />
+                    {% else %}
+                        {% ifequal settings_pack "default" %}
+                            {% trans "Your site is running in standard mode, click the button below to run in bootstrap mode." %}<br />
+                        {% else %}
+                            {% trans "Your site is running with some customized settings, click the buttons below to run with defaults or in bootstrap mode" %}
+                        {% endifequal %}
+                    {% endifequal %}
+                    {% ifnotequal settings_pack "default" %}
+                        <button onclick="if (window.confirm('{% trans "Are you sure you want to revert to the defaults?" %}')) window.location='{% url admin_go_defaults %}';">{% trans "revert to defaults" %}</button>
+                    {% endifnotequal %}
+                    {% ifnotequal settings_pack "bootstrap" %}
+                        <button onclick="if (window.confirm('{% trans "Are you sure you want to run bootstrap mode?" %}')) window.location='{% url admin_go_bootstrap %}';">{% trans "go bootstrap" %}</button>
+                    {% endifnotequal %}
+                </td>
+            </tr>
+            <tr>
+                <td>
+                    <em>"Bootstrap mode" relaxes the minimum required reputation to perform actions like voting and commenting.
+                    This is useful to help new communities get started.</em>
+                </td>
+            </tr>
+        </table>
+    </div>
+    <div class="module" style="width:98%; display: inline-block;">
+        <table width="100%">
+        <caption>{% trans "Recent activity" %}</caption>
+            <tr>
+                <td colspan="2">
+                    <table id="result_list" width="100%">
+                    {% for activity in recent_activity.paginator.page %}
+                        <tr class="{% cycle 'row1' 'row2' %}"><td>{% activity_item activity request.user %}</td></tr>
+                    {% endfor %}
+                    </table>
+                </td>
+            </tr>
+        </table>
+        <p class="paginator">
+            {{ recent_activity.paginator.page_numbers }}
+        </p>
+    </div>
+{% endblock %}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/djstyle_base.html b/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/djstyle_base.html
new file mode 100644 (file)
index 0000000..3527dc1
--- /dev/null
@@ -0,0 +1,144 @@
+{% load extra_tags extra_filters i18n %}
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+    <link rel="stylesheet" href="{{ settings.ADMIN_MEDIA_PREFIX }}css/base.css" type="text/css"/>
+    <link rel="stylesheet" href="{{ settings.ADMIN_MEDIA_PREFIX }}css/forms.css" type="text/css"/>
+    <link rel="stylesheet" href="{{ settings.ADMIN_MEDIA_PREFIX }}css/changelists.css" type="text/css"/>
+    <!--[if lte IE 7]><link rel="stylesheet" type="text/css" href="{{ settings.ADMIN_MEDIA_PREFIX }}css/ie.css" /><![endif]-->
+    <link rel="stylesheet" type="text/css" media="screen" href="{% media "/media/style/djstyle_admin.css" %}"/>
+    <script src="http://www.google.com/jsapi" type="text/javascript"></script>
+    <script type="text/javascript">
+    //<!--
+        google.load("jquery", "1.3");
+    //-->
+    </script>
+    <script type="text/javascript" src="{% media "/media/js/osqa.admin.js" %}"></script>
+    {% block adminjs %}{% endblock %}
+    <title>{% trans "OSQA administration area" %} - {% block subtitle %}{% endblock %}</title>
+</head>
+<body>
+<div id="container" class="change-list">
+        <div id="header">
+            {% block header %}
+            <div id="branding">
+                <h1 id="site-name">{{ settings.APP_SHORT_NAME }} - {% trans "Administration Area" %} </h1>
+            </div>
+            {% endblock %}
+            <div id="user-tools">
+                {% trans "Welcome," %}
+                <strong>{{ request.user.username }}</strong>.
+                <a href="{% url admin_switch_interface %}?to=default">{% trans "To standard interface" %}</a>
+                / <a href="{% url index %}">{% trans "Back to home page" %}</a>
+                / <a href="{% url logout %}">{% trans "Log out" %}</a>
+            </div>
+        </div>
+        <div class="breadcrumbs">
+            <a href="{% url index %}">{% trans "Home" %}</a> &gt;
+            <a href="{% url admin_index %}">{% trans "Dashboard" %}</a> &gt;
+            {% block pagename %}{% endblock %} - 
+            {% block description %}{% endblock %}
+        </div>
+        <div id="content" class="{% if hide_menu %}flex{% else %}colMS{% endif %}">
+            <div id="content-main">
+            {% autoescape off %}
+                {% for message in user_messages %}
+                    <p class="admin_message">{{ message }}</p>
+                {% endfor %}
+            {% endautoescape %}
+                {% block admincontent %}{% endblock %}
+            </div>
+            {% if not hide_menu %}
+            <div id="content-related">
+                {% if unsaved %}
+                <div id="changes-box" class="module">
+                    <h2>{% trans "Unpublished changes" %}</h2>
+                    <p>
+                        <img src="{{ settings.ADMIN_MEDIA_PREFIX }}img/admin/icon_alert.gif" />
+                        {% trans "Items marked with this icon have unpublished changes." %}
+                    </p>
+                </div>
+                {% endif %}
+                <div id="basic-sets-menu" class="module">
+                    <h2>{% trans "Basic settings" %}</h2>
+                    <ul>
+                        <li><a href="{% url admin_set allsets.basic.name %}">{{ allsets.basic.title }}</a></li>
+                        <li><a href="{% url admin_set allsets.users.name %}">{{ allsets.users.title }}</a></li>
+                        <li><a href="{% url admin_set allsets.email.name %}">{{ allsets.email.title }}</a></li>
+                        <li><a href="{% url admin_set allsets.paths.name %}">{{ allsets.paths.title }}</a></li>
+                        <li><a href="{% url admin_set allsets.urls.name %}">{{ allsets.urls.title }}</a></li>
+                        <li><a href="{% url admin_set allsets.extkeys.name %}">{{ allsets.extkeys.title }}</a></li>
+                    </ul>
+                </div>
+                <div id="workflow-sets-menu" class="module">
+                    <h2>{% trans "Workflow settings" %}</h2>
+                    <ul>
+                        <li><a href="{% url admin_set allsets.repgain.name %}">{{ allsets.repgain.title }}</a></li>
+                        <li><a href="{% url admin_set allsets.minrep.name %}">{{ allsets.minrep.title }}</a></li>
+                        <li><a href="{% url admin_set allsets.voting.name %}">{{ allsets.voting.title }}</a></li>
+                        <li><a href="{% url admin_set allsets.accept.name %}">{{ allsets.accept.title }}</a></li>
+                        <li><a href="{% url admin_set allsets.badges.name %}">{{ allsets.badges.title }}</a></li>
+                    </ul>
+                </div>
+                <div id="forum-sets-menu" class="module">
+                    <h2>{% trans "Forum settings" %}</h2>
+                    <ul>
+                        <li><a href="{% url admin_set allsets.form.name %}">{{ allsets.form.title }}</a></li>
+                        <li><a href="{% url admin_set allsets.view.name %}">{{ allsets.view.title }}</a></li>
+                        <li><a href="{% url admin_set allsets.moderation.name %}">{{ allsets.moderation.title }}</a></li>
+                    </ul>
+                </div>
+                <div id="pages-sets-menu" class="module">
+                    <h2>{% trans "Static content" %}</h2>
+                    <ul>
+                        <li><a href="{% url admin_static_pages %}">{% trans "Custom Pages" %}</a></li>
+                        <li><a href="{% url admin_set allsets.about.name %}">{{ allsets.about.title }}</a></li>
+                        <li><a href="{% url admin_set allsets.faq.name %}">{{ allsets.faq.title }}</a></li>
+                        <li><a href="{% url admin_set allsets.sidebar.name %}">{{ allsets.sidebar.title }}</a></li>
+                        <li>
+                            <a href="{% url admin_set allsets.css.name %}">{{ allsets.css.title }}</a>
+                            {% if "css"|contained_in:unsaved %}<img width="12" height="12" src="{{ settings.ADMIN_MEDIA_PREFIX }}img/admin/icon_alert.gif" alt="{% trans "Unsaved changes" %}" />{% endif %}
+                        </li>
+                        <li>
+                            <a href="{% url admin_set allsets.headandfoot.name %}">{{ allsets.headandfoot.title }}</a>
+                            {% if "headandfoot"|contained_in:unsaved %}<img width="12" height="12" src="{{ settings.ADMIN_MEDIA_PREFIX }}img/admin/icon_alert.gif" alt="{% trans "Unsaved changes" %}" />{% endif %}
+                        </li>
+                        <li>
+                            <a href="{% url admin_set allsets.head.name %}">{{ allsets.head.title }}</a>
+                            {% if "head"|contained_in:unsaved %}<img width="12" height="12" src="{{ settings.ADMIN_MEDIA_PREFIX }}img/admin/icon_alert.gif" alt="{% trans "Unsaved changes" %}" />{% endif %}
+                        </li>
+                    </ul>
+                </div>
+                <div id="other-sets-menu" class="module">
+                    <h2>{% trans "Other settings" %}</h2>
+                    <ul>
+                    {% for set in othersets %}
+                        <li>
+                            <a href="{% url admin_set set.name %}">{{ set.title }}</a>
+                            {% if set.name|contained_in:unsaved %}<img width="12" height="12" src="{{ settings.ADMIN_MEDIA_PREFIX }}img/admin/icon_alert.gif" alt="{% trans "Unsaved changes" %}" />{% endif %}
+                        </li>
+                    {% endfor %}
+                    </ul>
+                </div>
+                <div id="tools-menu" class="module">
+                    <h2>{% trans "Tools" %}</h2>
+                    <ul>
+                        <li><a href="{% url admin_maintenance %}">{% trans "Maintenance mode" %}</a></li>
+                        <li><a href="{% url admin_flagged_posts %}">{% trans "Flagged Posts" %}</a></li>
+                        {% for name,tool in tools.items %}
+                            <li><a href="{% url admin_tools name %}">{{ tool.label }}</a></li>
+                        {% endfor %}
+                    </ul>
+                </div>
+            </div>
+            {% endif %}
+        </div>
+        <div id="footer" class="breadcumbs">
+            <a href="http://www.osqa.net">OSQA</a> <span class="version">{{ settings.OSQA_VERSION }} ({{ settings.SVN_REVISION }})</span>
+        </div>
+    </div>
+</body>
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/edit_page.html b/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/edit_page.html
new file mode 100644 (file)
index 0000000..d8d251f
--- /dev/null
@@ -0,0 +1,36 @@
+{% extends basetemplate %}
+
+{% load i18n extra_filters %}
+
+{% block subtitle %}{% trans "Editing page" %}{% endblock %}
+{% block pagename %}
+    <a href="{% url admin_static_pages %}">{% trans "Static Pages" %}</a> &gt;
+    {% if page %}{% trans "Editing page" %}{% else %}{% trans "Creating page" %}{% endif %}
+{% endblock %}
+{% block description %}
+    {% if page %}{{ page.title }}{% else %}{% trans "New page" %}{% endif %}
+    ({% if published %}{% trans "Published" %}{% else %}{% trans "Unpublished" %}{% endif %})    
+{% endblock %}
+
+{% block admincontent %}
+    <form action="" method="post" accept-charset="utf-8">
+        <table style="width: 100%">
+        {{ form.as_table }}
+        <tr>
+            <th></th>
+            <td>
+                {% if page %}
+                    <input id="submit" name="submit" type="submit" value="{% trans "Edit" %}" />
+                {% else %}
+                    <input id="submit" name="submit" type="submit" value="{% trans "Save" %}" />
+                {% endif %}
+                {% if published %}
+                    <input id="unpublish" name="unpublish" type="submit" value="{% trans "Unpublish" %}" />
+                {% else %}
+                    <input id="publish" name="publish" type="submit" value="{% trans "Publish" %}" />
+                {% endif %}
+            </td>
+        </tr>
+        </table>
+    </form>
+{% endblock %}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/flagged_posts.html b/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/flagged_posts.html
new file mode 100644 (file)
index 0000000..a58d13e
--- /dev/null
@@ -0,0 +1,25 @@
+{% extends basetemplate %}
+
+{% load i18n %}
+{% load user_tags %}
+
+{% block subtitle %}{% trans "Flagged Posts" %}{% endblock %}
+{% block pagename %}{% trans "Flagged Posts" %}{% endblock %}
+{% block description %}{% trans "This are the posts that have been flagged by users." %}{% endblock %}
+
+{% block admincontent %}
+    <div class="module" style="width:98%; display: inline-block;">
+        <table width="100%">
+        <caption>{% trans "Flagged Posts" %}</caption>
+            <tr>
+                <td colspan="2">
+                    <table width="100%">
+                    {% for post in flagged_posts %}
+                        <tr><td>{% flagged_item post request.user %}</td></tr>
+                    {% endfor %}
+                    </table>
+                </td>
+            </tr>
+        </table>
+    </div>
+{% endblock %}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/graph.html b/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/graph.html
new file mode 100644 (file)
index 0000000..ee84f9e
--- /dev/null
@@ -0,0 +1,10 @@
+<div class="module" style="width:385px; height:300px; display: inline-block;">
+    <table style="width: 100%; height: 100%">
+        <caption>{{ graph.caption }}</caption>
+        <tr>
+            <td>
+                <div style="width: 100%; height: 100%" id="{{ graph.id }}"></div>
+            </td>
+        </tr>
+    </table>
+</div>
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/index.html b/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/index.html
new file mode 100644 (file)
index 0000000..30c3f65
--- /dev/null
@@ -0,0 +1,80 @@
+{% extends "osqaadmin/base.html" %}\r
+\r
+{% load i18n %}\r
+{% load user_tags %}\r
+\r
+{% block subtitle %}\r
+    {% trans "Dashboard" %}\r
+{% endblock %}\r
+{% block description %}\r
+    {% trans "Welcome to the OSQA administration area." %}\r
+{% endblock %}\r
+\r
+{% block admincontent %}\r
+    <table width="100%">\r
+        <tr>\r
+            <td width="50%" valign="top">\r
+                <h3>{%trans "Site statistics" %}</h3>\r
+                <table>\r
+                    <tr>\r
+                        <td>\r
+                        {{ statistics.total_questions }} {% trans "question" %}{{ statistics.total_questions|pluralize }} ({{ statistics.questions_last_24 }} {% trans "in the last 24 hours" %})\r
+                        </td>\r
+                    </tr>\r
+                    <tr>\r
+                        <td>\r
+                        {{ statistics.total_answers }} {% trans "answer" %}{{ statistics.total_answers|pluralize }} ({{ statistics.answers_last_24 }} {% trans "in the last 24 hours" %})\r
+                        </td>\r
+                    </tr>\r
+                    <tr>\r
+                        <td>\r
+                        {{ statistics.total_users }} {% trans "user" %}{{ statistics.total_users|pluralize }} ({{ statistics.users_last_24 }} {% trans "joined in the last 24 hours" %})\r
+                        </td>\r
+                    </tr>\r
+                </table>\r
+            </td>\r
+            <td valign="top">\r
+                <h3>{%trans "Site status" %}</h3>\r
+                <table>\r
+                    <tr>\r
+                        <td>\r
+                            {% ifequal settings_pack "bootstrap" %}\r
+                                {% trans "Your site is running in bootstrap mode, click the button below to revert to defaults." %}<br />\r
+                            {% else %}\r
+                                {% ifequal settings_pack "default" %}\r
+                                    {% trans "Your site is running in standard mode, click the button below to run in bootstrap mode." %}<br />\r
+                                {% else %}\r
+                                    {% trans "Your site is running with some customized settings, click the buttons below to run with defaults or in bootstrap mode" %}\r
+                                {% endifequal %}\r
+                            {% endifequal %}\r
+                            {% ifnotequal settings_pack "default" %}\r
+                                <button onclick="if (window.confirm('{% trans "Are you sure you want to revert to the defaults?" %}')) window.location='{% url admin_go_defaults %}';">{% trans "revert to defaults" %}</button>\r
+                            {% endifnotequal %}\r
+                            {% ifnotequal settings_pack "bootstrap" %}\r
+                                <button onclick="if (window.confirm('{% trans "Are you sure you want to run bootstrap mode?" %}')) window.location='{% url admin_go_bootstrap %}';">{% trans "go bootstrap" %}</button>\r
+                            {% endifnotequal %}\r
+                        </td>\r
+                    </tr>\r
+                    <tr>\r
+                        <td>\r
+                            <em>"Bootstrap mode" relaxes the minimum required reputation to perform actions like voting and commenting.\r
+                            This is useful to help new communities get started.</em>\r
+                        </td>\r
+                    </tr>\r
+                </table>\r
+                <h3>{%trans "Recalculate scores and reputation" %}</h3>\r
+                 <button onclick="if (window.confirm('{% trans "This is a heavy operation, are you sure?" %}')) window.location='{% url admin_denormalize %}';">{% trans "Recalculate" %}</button>\r
+            </td>\r
+        </tr>\r
+        <tr>\r
+            <td colspan="2">\r
+                <h3>{% trans "Recent activity" %}</h3>\r
+                <table width="100%">\r
+                {% for activity in recent_activity %}\r
+                    {% activity_item activity request.user %}\r
+                {% endfor %}\r
+                </table>\r
+            </td>\r
+        </tr>\r
+    </table>        \r
+{% endblock %}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/maintenance.html b/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/maintenance.html
new file mode 100644 (file)
index 0000000..38d1d0e
--- /dev/null
@@ -0,0 +1,25 @@
+{% extends basetemplate %}
+
+{% load i18n %}
+
+{% block subtitle %}{% trans "Maintenance mode" %}{% endblock %}
+{% block pagename %}{% trans "Maintenance mode" %}{% endblock %}
+{% block description %}{% trans "Maintainance mode allows you to close your site for maintainance, allowing only a predetermined set of ip addresses to access it normally." %}{% endblock %}
+
+{% block admincontent %}
+<form method="POST" action="">
+    {% if in_maintenance %}
+        <h1>{% trans "Your site is currently running on maintenance mode." %}</h1>
+        <p>{% trans "You can adjust the settings bellow" %}</p>
+    {% endif %}
+    <table>
+    {{ form.as_table }}
+    </table>
+    {% if in_maintenance %}
+        <input type="submit" name="adjust" value="{% trans "Adjust settings" %}" />
+        <input type="submit" name="open" value="{% trans "Open site" %}" />
+    {% else %}
+        <input type="submit" name="close" value="{% trans "Close for maintenance" %}" />
+    {% endif %}
+</form>
+{% endblock %}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/moderation.html b/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/moderation.html
new file mode 100644 (file)
index 0000000..688c897
--- /dev/null
@@ -0,0 +1,101 @@
+{% extends basetemplate %}
+
+{% load i18n humanize %}
+
+{% block subtitle %}{% trans "Moderation" %}{% endblock %}
+{% block pagename %}{% trans "Moderation" %}{% endblock %}
+{% block description %}{% trans "These tools allow you to search for undesired behaviours and cheating patterns." %}{% endblock %}
+
+{% block admincontent %}
+    <div class="module">
+        <form action="" id="changelist" method="POST">
+            <div class="actions">
+                {% trans "Verify:" %}
+                <input type="text" size="3" name="limit" id="filter-limit" value="5" />
+                <select name="sort" id="filter-sort">
+                    <option value="high-rep">{% trans "highest ranking users" %}</option>
+                    <option value="newer">{% trans "newer users" %}</option>
+                    <option value="older">{% trans "older users" %}</option>
+                    <option value="ids">{% trans "users with these ids" %}</option>
+                </select>
+                <span id="filter-ids" style="display: none">
+                    <input type="text" name="ids" size="15" />
+                    <small>{% trans "(Comma separated list of user ids)" %}</small>
+                </span>
+                <input type="submit" value="{% trans "Go" %}" />
+            </div>
+        </form>
+        <script type="text/javascript">
+            $(function() {
+                $limit = $('#filter-limit');
+                $sort = $('#filter-sort');
+                $ids = $('#filter-ids');
+
+                function verify_sort() {
+                    if ($sort.val() == "ids") {
+                        $ids.show();
+                        $limit.hide();
+                    } else {
+                        $ids.hide();
+                        $limit.show();
+                    }
+                }
+
+                verify_sort();
+                $sort.change(verify_sort);
+            })
+        </script>
+        {% if cheaters %}
+        <table cellspacing="0" width="100%">
+            <caption>{% trans "Possible cheaters" %}</caption>
+            {% for cheater, fakes in cheaters %}
+            <tr>
+                <td>
+                    <div class="cheater-info">
+                        <p><a href="{{ cheater.get_profile_url }}">{{ cheater.username }}</a></p>
+                        <p><b>{% trans "Email" %}</b>
+                        {% if cheater.email_isvalid %}
+                            <img src="{{ settings.ADMIN_MEDIA_PREFIX }}img/admin/icon-yes.gif" alt="{% trans "Validated" %}" />
+                        {% else %}
+                            <img src="{{ settings.ADMIN_MEDIA_PREFIX }}img/admin/icon-no.gif" alt="{% trans "Not validated" %}" />
+                        {% endif %}
+                        <a href="mailto: {{ cheater.email }}">{{ cheater.email }}</a></p>
+                        <p><b>{% trans "Reputation:" %}</b> {{ cheater.reputation|intcomma }}</p>
+                    </div>
+                    <table cellspacing="0" width="100%">
+                        <thead>
+                            <tr>
+                                <th>{% trans "Profile" %}</th>
+                                <th>{% trans "Email" %}</th>
+                                <th>{% trans "Reputation" %}</th>
+                                <th>{% trans "Affecting actions" %}</th>
+                                <th>{% trans "Cross ips" %}</th>
+                                <th>{% trans "Cheating score" %}</th>
+                            </tr>
+                        </thead>
+                        <caption>{% trans "Possible fake accounts" %}</caption>
+                        {% for fake in fakes %}
+                            <tr>
+                                <td><a href="{{ fake.get_profile_url }}">{{ fake.username }}</a></td>
+                                <td>
+                                    {% if fake.email_isvalid %}
+                                        <img src="{{ settings.ADMIN_MEDIA_PREFIX }}img/admin/icon-yes.gif" alt="{% trans "Validated" %}" />
+                                    {% else %}
+                                        <img src="{{ settings.ADMIN_MEDIA_PREFIX }}img/admin/icon-no.gif" alt="{% trans "Not validated" %}" />
+                                    {% endif %}
+                                    <a href="mailto: {{ fake.email }}">{{ fake.email }}</a>
+                                </td>
+                                <td>{{ fake.reputation|intcomma }}</td>
+                                <td>{{ fake.fdata.affect_count }} {% trans "out of" %} {{ fake.fdata.total_actions }} ({{ fake.fdata.action_ratio|stringformat:".2f" }}%)</td>
+                                <td>{{ fake.fdata.cross_ip_count }} {% trans "out of" %} {{ fake.fdata.total_ip_count }} ({{ fake.fdata.cross_ip_ratio|stringformat:".2f" }}%)</td>
+                                <td>{{ fake.fdata.fake_score|stringformat:".2f" }}</td>
+                            </tr>
+                        {% endfor %}
+                    </table>
+                </td>
+            </tr>
+            {% endfor %}
+        </table>
+        {% endif %}
+    </div>
+{% endblock %}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/nodeman.html b/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/nodeman.html
new file mode 100644 (file)
index 0000000..997fab5
--- /dev/null
@@ -0,0 +1,513 @@
+{% extends basetemplate %}
+
+{% load i18n user_tags extra_tags extra_filters %}
+
+{% block adminjs %}
+    <script type="text/javascript">
+        $(function() {
+            var $form = $('#changelist-search');
+
+            $('#all-node-type-link').click(function() {
+                $('#type-filter-container').find('input').remove();
+                $form.submit();
+            });
+
+            $('.node-type-link').click(function() {
+                var link_type = $(this).attr('href').substring(1);
+
+                if ($('#type-filter-container').find('input[value=' + link_type + ']').length == 0) {
+                    $('#type-filter-container').append($("<input name=\"node_type\" type=\"hidden\" value=\"" + link_type + "\" />"));
+                } else {
+                    $('#type-filter-container').find('input[value=' + link_type + ']').remove();
+                }
+
+                $form.submit();                
+            });
+
+            $('#all-state-link').click(function() {
+                $('#state-filter-container').find('input').remove();
+                $form.submit();
+            });
+
+            $('.state-type-link').click(function() {
+                var state_type = $(this).attr('href').substring(1);
+
+                if ($('#state-filter-container').find('input[value=' + state_type + ']').length == 0) {
+                    $('#state-filter-container').append($("<input name=\"state_type\" type=\"hidden\" value=\"" + state_type + "\" />"));
+                } else {
+                    $('#state-filter-container').find('input[value=' + state_type + ']').remove();
+                }
+
+                $form.submit();
+            });
+
+            $('.action-select').change(function() {
+                $('#action-toggle').removeAttr('checked');
+                var $tr = $(this).parents('tr');
+                if ($(this).attr('checked')) {
+                    $tr.addClass('selected');
+                } else {
+                    $tr.removeClass('selected');
+                }
+            }).change();
+
+            $('#action-toggle').change(function() {
+                var $rows = $('#result_list').find('tbody').find('tr');
+                var $boxes = $('#result_list').find('tbody').find('input');
+
+                if ($(this).attr('checked')) {
+                    $rows.addClass('selected');
+                    $boxes.attr('checked', 'checked')
+                } else {
+                    $rows.removeClass('selected');
+                    $boxes.removeAttr('checked');
+                }
+            });
+
+            $('#author-selector').autocomplete('{% url matching_users %}', {
+                minChars: 1,
+                matchContains: true,
+                max: 10,
+
+                formatItem: function(row, i, max, value) {
+                    return row[1] + ' (' + row[2] + ' {% trans "rep" %})';
+                },
+
+                formatResult: function(row, i, max, value){
+                    return row[1];
+                }
+            });
+
+            $('#author-selector').result(function(event, data, formatted) {
+                if ($('#author-filter-container').find('input[value=' + data[0] + ']').length == 0) {
+                    $('#author-filter-container').append($("<input name=\"authors\" type=\"hidden\" value=\"" + data[0] + "\" />"));
+                    $form.submit();
+                }
+            });
+
+            $('.author-filter-remover').click(function() {
+                var id = $(this).attr('rel');
+                if ($('#author-filter-container').find('input[value=' + id + ']').length > 0) {
+                    $('#author-filter-container').find('input[value=' + id + ']').remove();
+                    $form.submit();
+                }
+            });
+
+            $('#tag-selector').autocomplete('{% url matching_tags %}', {
+                minChars: 1,
+                matchContains: true,
+                max: 10,
+
+                formatItem: function(row, i, max, value) {
+                    return row[1] + ' (' + row[2] + ' {% trans "uses" %})';
+                },
+
+                formatResult: function(row, i, max, value){
+                    return row[1];
+                }
+            });
+
+            $('#tag-selector').result(function(event, data, formatted) {
+                if ($('#tag-filter-container').find('input[value=' + data[0] + ']').length == 0) {
+                    $('#tag-filter-container').append($("<input name=\"tags\" type=\"hidden\" value=\"" + data[0] + "\" />"));
+                    $form.submit();
+                }
+            });
+
+            $('.tag-filter-remover').click(function() {
+                var id = $(this).attr('rel');
+                if ($('#tag-filter-container').find('input[value=' + id + ']').length > 0) {
+                    $('#tag-filter-container').find('input[value=' + id + ']').remove();
+                    $form.submit();
+                }
+            });
+
+            $('#filter-name-box').one('focus', function() {
+                $(this).val('');
+                $(this).css('color', 'black');
+            });
+
+            $('#filter-name-box').keyup(function() {
+                if ($(this).val().trim().length > 0) {
+                    $('#save-filter-button').removeAttr('disabled');
+                    $('#save-filter-button').css('color', 'black');
+                } else {
+                    $('#save-filter-button').css('color', '#AAA');
+                    $('#save-filter-button').attr('disabled', 'disabled');
+                }
+            });
+
+            var resize_data = null;
+
+            $('.col-resizer').mousedown(function(e) {
+                var $to_resize = $(this).prev();
+
+                resize_data = {
+                    resizer: $(this),
+                    to_resize: $to_resize,
+                    start_width: $to_resize.innerWidth(),
+                    x_start: e.pageX,
+                }
+            });
+
+            $('body').mousemove(function(e) {
+                if (resize_data != null) {
+                    var new_size = (resize_data.start_width - (resize_data.x_start - e.pageX)) + 'px';
+                    resize_data.to_resize.css({'max-width': new_size, 'min-width': new_size})
+                    resize_data.resizer.css('max-width', '3px');
+                }
+            });
+
+            $('body').mouseup(function() {
+                if (resize_data != null)
+                    resize_data = null;
+            });
+
+            $('#filter-panel-header').click(function() {
+                $('#filter-panel').slideToggle();
+            });
+
+            $('#state-filter-type').change(function() {
+                $('#state-filter-type-hidden').val($(this).val());
+                $form.submit();
+            });
+            
+            $('#reset-text-filter').click(function() {
+                $('#text-filter-input').val('');
+                $form.submit();
+                return false;
+            });
+        });
+    </script>
+    <style>
+        #toolbar ul li {
+            list-style-type: none;
+            display: inline;
+            margin-right: 12px;
+        }
+
+        #result_list tr td.deleted {
+            background-color: #FDD;
+            border-bottom: 1px solid #a9a9a9;
+        }
+
+        #result_list tr td.accepted {
+            background-color: #DFD;
+            border-bottom: 1px solid #a9a9a9;
+        }
+
+        span.question-deleted {
+            text-decoration: line-through;
+        }
+
+        .col-resizer {
+            width: 2px;
+            min-width: 2px;
+            min-width: 2px;
+            cursor: col-resize;
+            padding: 0 0 0 0;
+        }
+    </style>
+    <script type="text/javascript">window.__admin_media_prefix__ = "{{ settings.ADMIN_MEDIA_PREFIX }}";</script>
+    <link href="{{ settings.ADMIN_MEDIA_PREFIX }}css/base.css" rel="stylesheet" type="text/css" media="screen" />
+    <script type="text/javascript">
+    /* gettext identity library */
+
+    function gettext(msgid) { return msgid; }
+    function ngettext(singular, plural, count) { return (count == 1) ? singular : plural; }
+    function gettext_noop(msgid) { return msgid; }
+
+    function interpolate(fmt, obj, named) {
+      if (named) {
+        return fmt.replace(/%\(\w+\)s/g, function(match){return String(obj[match.slice(2,-2)])});
+      } else {
+        return fmt.replace(/%s/g, function(match){return String(obj.shift())});
+      }
+    }
+
+    /* formatting library */
+
+    var formats = new Array();
+
+    formats['DATETIME_FORMAT'] = 'N j, Y, P';
+    formats['DATE_FORMAT'] = 'N j, Y';
+    formats['DECIMAL_SEPARATOR'] = '.';
+    formats['MONTH_DAY_FORMAT'] = 'F j';
+    formats['NUMBER_GROUPING'] = '0';
+    formats['TIME_FORMAT'] = 'P';
+    formats['FIRST_DAY_OF_WEEK'] = '0';
+    formats['TIME_INPUT_FORMATS'] = ['%H:%M:%S', '%H:%M'];
+    formats['THOUSAND_SEPARATOR'] = ',';
+    formats['DATE_INPUT_FORMATS'] = ['%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', '%b %d %Y', '%b %d, %Y', '%d %b %Y', '%d %b, %Y', '%B %d %Y', '%B %d, %Y', '%d %B %Y', '%d %B, %Y'];
+    formats['YEAR_MONTH_FORMAT'] = 'F Y';
+    formats['SHORT_DATE_FORMAT'] = 'm/d/Y';
+    formats['SHORT_DATETIME_FORMAT'] = 'm/d/Y P';
+    formats['DATETIME_INPUT_FORMATS'] = ['%Y-%m-%d %H:%M:%S', '%Y-%m-%d %H:%M', '%Y-%m-%d', '%m/%d/%Y %H:%M:%S', '%m/%d/%Y %H:%M', '%m/%d/%Y', '%m/%d/%y %H:%M:%S', '%m/%d/%y %H:%M', '%m/%d/%y'];
+
+    function get_format(format_type) {
+        var value = formats[format_type];
+        if (typeof(value) == 'undefined') {
+          return msgid;
+        } else {
+          return value;
+        }
+    }
+    
+    </script>
+    <script type="text/javascript" src="{{ settings.ADMIN_MEDIA_PREFIX }}js/core.js"></script>
+{% endblock %}
+
+{% block subtitle %}
+    {% trans "Node manager" %}
+{% endblock %}
+{% block description %}
+    {% trans "Nodes bulk management" %}
+{% endblock %}
+
+{% block admincontent %}
+    <div id="changelist" class="module filtered">
+        <div id="toolbar">
+            <form method="get" action="" id="changelist-search">
+            <div>
+                <div>
+                    <label><img alt="Search" src="{{ settings.ADMIN_MEDIA_PREFIX }}img/admin/icon_searchbox.png"></label>
+                    <input type="text" size="40" name="text" id="text-filter-input" value="{{ text }}">
+                    <input type="submit" value="{% trans "Search" %}">
+                    {% if text %}
+                        <small><a href="#" id="reset-text-filter">{% trans "reset text filter" %}</a></small>
+                    {% endif %}
+                    <br />
+                    <ul>
+                        <li>
+                            <label>
+                                <input type="radio" name="text_in" value="title"{% ifequal text_in "title" %} checked="checked"{% endifequal %} />
+                            {% trans "Title" %}</label>
+                        </li>
+                        <li>
+                            <label>
+                                <input type="radio" name="text_in" value="body"{% ifequal text_in "body" %} checked="checked"{% endifequal %} />
+                            {% trans "Body" %}</label>
+                        </li>
+                        <li>
+                            <label>
+                                <input type="radio" name="text_in" value="both"{% ifequal text_in "both" %} checked="checked"{% endifequal %} />
+                            {% trans "Title and Body" %}</label>
+                       </li>
+                    </ul>
+                </div>
+            </div>
+            <input type="hidden" name="sort" value="{{ nodes.paginator.current_sort }}" />
+            <input type="hidden" id="state-filter-type-hidden" name="state_filter_type" value="" />
+            <div style="display: none;" id="author-filter-container">
+                {% for u in authors %}
+                <input name="authors" type="hidden" value="{{ u.id }}" />
+                {% endfor %}
+            </div>
+            <div style="display: none;" id="tag-filter-container">
+                {% for t in tags %}
+                <input name="tags" type="hidden" value="{{ t.id }}" />
+                {% endfor %}
+            </div>
+            <div id="type-filter-container" style="display: none;">
+                {% for type in type_filter %}
+                <input name="node_type" type="hidden" value="{{ type }}" />
+                {% endfor %}
+            </div>
+            <div id="state-filter-container" style="display: none;">
+                {% for type in state_filter %}
+                <input name="state_type" type="hidden" value="{{ type }}" />
+                {% endfor %}
+            </div>
+            </form>
+        </div>
+        <div id="changelist-filter">
+            <h2 id="filter-panel-header">{% trans "Filter" %}<small> ({% trans "Click to show/hide" %})</small></h2>
+            <div id="filter-panel">
+            <h3>{% trans "By type" %}</h3>
+            <ul>
+                <li {% if not type_filter %} class="selected"{% endif %}>
+                    <a id="all-node-type-link" href="#all" title="{% trans "click to clear the type filter" %}">{% trans "all" %}</a>
+                </li>
+                {% for type, name in node_types %}
+                <li{% if type|contained_in:type_filter %} class="selected" title="{% trans "click to remove from the filter" %}"{% else %} title="{% trans "click to add to the filter" %}"{% endif %}>
+                    <a class="node-type-link" href="#{{ type }}">{{ name }}</a>
+                </li>
+                {% endfor %}
+            </ul>
+            <h3>{% trans "By state" %}</h3>
+            <ul>
+                <li {% if not state_filter %} class="selected"{% endif %}>
+                    <a id="all-state-link" href="#any" title="{% trans "click to clear the state filter" %}">{% trans "any" %}</a>
+                </li>
+                {% for state_type in state_types %}
+                    <li{% if state_type|contained_in:state_filter %} class="selected" title="{% trans "click to remove from the filter" %}"{% else %} title="{% trans "click to add to the filter" %}"{% endif %}>
+                        <a class="state-type-link" href="#{{ state_type }}">{{ state_type }}</a>
+                    </li>
+                {% endfor %}
+                <li>
+                    <select id="state-filter-type">
+                        <option value="any"{% ifequal state_filter_type "any" %} selected="selected"{% endifequal %}>{% trans "Match any selected" %}</option>
+                        <option value="all"{% ifequal state_filter_type "all" %} selected="selected"{% endifequal %}>{% trans "Match all selected" %}</option>
+                    </select>
+                </li>
+            </ul>
+            <h3>{% trans "By author(s)" %}</h3>
+            {% if not authors.count %}
+                <small>{% trans "No users selected, use the box bellow to add users to the filter." %}</small>
+            {% else %}
+                <ul>
+                    {% for u in authors %}
+                        <li class="selected">
+                            <img class="author-filter-remover" rel="{{ u.id }}" src="{% media "/media/images/close-small-dark.png" %}">
+                            {{ u.decorated_name }} ({{ u.reputation }})
+                        </li>
+                    {% endfor %}
+                </ul>
+                <small>{% trans "Click on the cross next to a user name to remove it from the filter." %}</small>
+            {% endif %}
+            <input type="text" size="20" autocomplete="off" id="author-selector" />
+
+            <h3>{% trans "By tag(s)" %}</h3>
+            {% if not tags.count %}
+                <small>{% trans "No tags selected, use the box bellow to add tags to the filter." %}</small>
+            {% else %}
+                <ul>
+                    {% for t in tags %}
+                        <li class="selected">
+                            <img class="tag-filter-remover" rel="{{ t.id }}" src="{% media "/media/images/close-small-dark.png" %}">
+                            {{ t.name }} ({{ t.used_count }})
+                        </li>
+                    {% endfor %}
+                </ul>
+                <small>{% trans "Click on the cross next to a tag name to remove it from the filter." %}</small>
+            {% endif %}
+            <input type="text" size="20" autocomplete="off" id="tag-selector" />
+
+            <h3>{% trans "Pre defined" %}</h3>
+            {% if not settings.NODE_MAN_FILTERS %}
+                <small>{% trans "There are no saved filters. Click bellow to add." %}</small>
+            {% endif %}
+            <ul id="pre-filter-container">
+                {% for name, uri in settings.NODE_MAN_FILTERS %}
+                <li class="selected"><a href="{% url admin_tools "nodeman" %}?{{ uri }}">{{ name }}</a></li>
+                {% endfor %}
+            </ul>
+            <form action="" method="POST">
+                <input name="filter_name" type="text" size="20" id="filter-name-box" style="color: #AAA;" value="{% trans "Filter name..." %}" />
+                <button name="save_filter" value="0" style="color: #AAA;" title="{% trans "Click to save the current filter" %}" id="save-filter-button" disabled="disabled" class="button">{% trans "Save" %}</button>
+            </form>
+
+            {% comment %}<h3>{% trans "Show" %}</h3>
+            <form action="" method="get">
+                <div>{{ show_form.show }}</div>
+                <input type="submit" value="{% trans "Refresh" %}" />
+            </form>{% endcomment %}
+            </div>
+        </div>
+        <form id="changelist-form" method="POST" action="">
+            <div class="actions">
+                <label>
+                    {% trans "Action" %}:
+                    <select name="action">
+                        <option selected="selected" value="">---------</option>
+                        <option value="delete_selected">{% trans "Mark deleted" %}</option>
+                        <option value="undelete_selected">{% trans "Undelete" %}</option>
+                        <option value="hard_delete_selected">{% trans "Delete completely" %}</option>
+                        <option value="close_selected">{% trans "Close (questions only)" %}</option>
+                    </select>
+                </label>
+                <button value="0" name="execute" title="{% trans "Run the selected action" %}" class="button" type="submit">{% trans "Go" %}</button>
+            </div>
+            <table id="result_list" cellspacing="0">
+                <thead>
+                    <tr>
+                        {% declare %}
+                            current_sort = nodes.paginator.current_sort
+                            added_at = current_sort == "added_at" and "ascending" or (current_sort == "added_at_asc" and "descending" or "")
+                            author = current_sort == "author" and "ascending" or (current_sort == "author_asc" and "descending" or "")
+                            score = current_sort == "score" and "ascending" or (current_sort == "score_asc" and "descending" or "")
+                            act_at = current_sort == "act_at" and "ascending" or (current_sort == "act_at_asc" and "descending" or "")
+                            act_by = current_sort == "act_by" and "ascending" or (current_sort == "act_by_asc" and "descending" or "")
+
+                            added_at_link = current_sort == "added_at" and nodes.paginator.added_at_asc_sort_link or nodes.paginator.added_at_sort_link
+                            author_link = current_sort == "author_asc" and nodes.paginator.author_sort_link or nodes.paginator.author_asc_sort_link
+                            score_link = current_sort == "score" and nodes.paginator.score_asc_sort_link or nodes.paginator.score_sort_link
+                            act_at_link = current_sort == "act_at" and nodes.paginator.act_at_asc_sort_link or nodes.paginator.act_at_sort_link
+                            act_by_link = current_sort == "act_by_asc" and nodes.paginator.act_by_sort_link or nodes.paginator.act_by_asc_sort_link
+                        {% enddeclare %}
+                        {% spaceless %}
+                        <th class="action-checkbox-column">
+                            <input type="checkbox" id="action-toggle" style="display: inline;" />
+                        </th>                        
+                        <th>{% trans "Type" %}</th>
+                        <th>{% trans "Summary" %}</th>
+                        <th class="col-resizer"></th>
+                        <th>{% trans "State" %}</th>
+                        <th class="sorted {{ author }}">
+                            <a href="{{ author_link }}">{% trans "Author" %}</a>
+                        </th>
+                        <th class="sorted {{ added_at }}">
+                            <a href="{{ added_at_link }}">{% trans "Added at" %}</a>
+                        </th>
+                        <!--<th class="sorted {{ score }}">
+                            <a href="{{ score_link }}">{% trans "Score" %}</a>
+                        </th>-->
+                        <th class="sorted {{ act_by }}">
+                            <a href="{{ act_by_link }}">{% trans "Last activity by" %}</a>
+                        </th>
+                        <th class="sorted {{ act_at }}">
+                            <a href="{{ act_at_link }}">{% trans "Last activity at" %}</a>
+                        </th>
+                        <th>{% trans "Tags" %}</th>
+                        {% endspaceless %}
+                    </tr>
+                </thead>
+                <tbody>
+                {% with filter_form.state_type.data as state_type %}
+                {% for node in nodes.paginator.page %}
+                    <tr class="{% cycle 'row1' 'row2' %}">
+                        <td><input type="checkbox" name="_selected_node" value="{{ node.id }}" class="action-select"></td>
+                        <td>{{ node.friendly_name }}</td>
+                        {% declare %}
+                            is_root = node.abs_parent == None
+                            title = is_root and node.title or node.abs_parent.title
+
+                            anchor = "<strong>%s</strong>" % html.hyperlink(node.get_absolute_url(), title)
+                            anchor = ((not is_root) and node.abs_parent.nis.deleted) and "<span class=\"question-deleted\">%s</span>" % anchor or anchor
+                            anchor = is_root and anchor or "(%s)" % anchor
+                            anchor = html.mark_safe(anchor)
+
+                            td_class = ""
+                            td_class = node.nis.accepted and "accepted" or td_class
+                            td_class = node.nis.deleted and "deleted" or td_class
+                        {% enddeclare %}
+                        <td class="{{ td_class }}" colspan="2">
+                            {{ anchor }}<br />
+                            {{ node.summary }}
+                        </td>
+                        <td>
+                            {% for state in node.states.all %}
+                            <b>{{ state.state_type }}</b> {% diff_date state.action.at %} {% trans "by" %}
+                            <a target="_blank" href="{{ state.action.by.get_absolute_url }}">{{ state.action.by.decorated_name }}</a><br />
+                            {% endfor %}
+                        </td>
+                        <td><a href="{{ node.author.get_absolute_url  }}">{{ node.author.decorated_name }}</a></td>
+                        <td>{% diff_date node.added_at %}</td>
+                        <!--<td>{{ node.score }}</td>-->
+                        <td><a href="{{ node.last_activity_by.get_absolute_url  }}">{{ node.last_activity_by.decorated_name }}</a></td>
+                        <td>{% diff_date node.last_activity_at %}</td>
+                        <td>
+                            {% for t in node.tags.all %}
+                                {% if t|contained_in:tags %}<b>{{ t.name }}</b>
+                                {% else %}{{ t.name }}{% endif %}
+                            {% endfor %}
+                        </td>
+                    </tr>
+                {% endfor %}
+                {% endwith %}
+                </tbody>
+            </table>
+            {{ nodes.paginator.page_numbers }}
+        </form>
+    </div>
+{% endblock %}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/set.html b/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/set.html
new file mode 100644 (file)
index 0000000..5cc427d
--- /dev/null
@@ -0,0 +1,27 @@
+{% extends basetemplate %}\r
+\r
+{% load i18n extra_tags extra_filters %}\r
+\r
+{% block subtitle %}{{ form.set.title }}{% endblock %}\r
+{% block pagename %}{{ form.set.title }}{% endblock %}\r
+{% block description %}{{ form.set.description }}{% endblock %}\r
+\r
+{% block admincontent %}\r
+    <form action="" method="POST" enctype="multipart/form-data" accept-charset="utf-8">\r
+        <table id="admin_form" style="width: 100%">\r
+            {{ form.as_table }}\r
+            <tr>\r
+                <th></th>\r
+                <td>\r
+                    <input id="submit" name="submit" type="submit" value="{% trans "Save" %}" onclick="this.form.target=''; return true;" />\r
+                    {% if form.set.can_preview %}\r
+                        <input id="preview" name="preview" type="submit" value="{% trans "Preview" %}" onclick="this.form.target='_blank'; return true;" />\r
+                        {% if form.set.name|contained_in:unsaved %}\r
+                            <input id="reset" name="reset" type="submit" value="{% trans "Reset Changes" %}" onclick="this.form.target=''; return true;" />\r
+                        {% endif %}\r
+                    {% endif %}\r
+                </td>\r
+            </tr>\r
+        </table>\r
+    </form>\r
+{% endblock %}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/static_pages.html b/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/static_pages.html
new file mode 100644 (file)
index 0000000..7d0e567
--- /dev/null
@@ -0,0 +1,28 @@
+{% extends basetemplate %}
+
+{% load i18n %}
+
+{% block subtitle %}{% trans "Static pages" %}{% endblock %}
+{% block pagename %}{% trans "Static pages" %}{% endblock %}
+{% block description %}{% trans "Allows you to create a set of static pages" %}{% endblock %}
+
+{% block admincontent %}
+    <h1>{% trans "Select page to edit" %}</h1>
+    <ul class="object-tools">
+        <li><a class="addlink" href="{% url admin_new_page %}">{% trans "New page" %}</a></li>
+    </ul>
+    <div class="module">
+        <table style="width: 100%">
+            <caption>{% trans "Pages" %}</caption>
+            <tbody>
+                {% for page in pages %}
+                    <tr>
+                        <th scope="row"><a href="{% url admin_edit_page id=page.id %}">{{ page.headline }}</a></th>
+                        <td><a class="changelink" href="{% url admin_edit_page id=page.id %}">{% trans "Edit" %}</a></td>
+                    </tr>
+                {% endfor %}
+            </tbody>
+        </table>
+    </div>
+
+{% endblock %}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/statistics.html b/forum/modules/template_loader.py/forum/skins/default/templates/osqaadmin/statistics.html
new file mode 100644 (file)
index 0000000..e012522
--- /dev/null
@@ -0,0 +1,33 @@
+{% extends basetemplate %}
+
+{% load i18n %}
+{% load extra_tags %}
+
+{% block adminjs %}
+<script type='text/javascript' src='{% media  "/media/js/excanvas.min.js" %}'></script>
+<script type='text/javascript' src='{% media  "/media/js/jquery.flot.min.js" %}'></script>
+<script type="text/javascript">
+        $().ready(function(){
+        {% for graph in graphs %}
+            var {{ graph.id }} = {{ graph.data }};
+            var {{ graph.id }}_placeholder = $('#{{ graph.id }}');
+
+            $.plot({{ graph.id }}_placeholder, [{{ graph.id }}], {
+                xaxis: { mode: "time" },
+                points: { show: false },
+                lines: { show: true }
+            });
+        {% endfor %}
+        });
+</script>
+{% endblock %}
+
+{% block subtitle %}{% trans "Dashboard" %}{% endblock %}
+{% block pagename %}{% trans "Dashboard" %}{% endblock %}
+{% block description %}{% trans "Some simple graphics to help you get a notion of whats going on in your site." %}{% endblock %}
+
+{% block admincontent %}
+{% for graph in graphs %}
+    {% include "osqaadmin/graph.html" %}
+{% endfor %}
+{% endblock %}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/page.html b/forum/modules/template_loader.py/forum/skins/default/templates/page.html
new file mode 100644 (file)
index 0000000..cf9b459
--- /dev/null
@@ -0,0 +1,27 @@
+{% extends base %}
+{% load i18n markup node_tags general_sidebar_tags %}
+{% block title %}{% spaceless %}{{ page.title }}{% endspaceless %}{% endblock %}
+
+{% block content %}
+<div class="headNormal">{{ page.title }}</div>
+<div class="content">
+{{ body }}
+</div>
+{% if page.extra.comments %}
+    {% comments page request.user %}
+{% endif %}
+{% endblock %}
+
+{% ifequal page.extra.template "sidebar" %}
+    {% block sidebar %}
+        {% sidebar_upper %}
+        {% if page.extra.sidebar %}
+            {% if page.extra.sidebar_wrap %}<div class="boxC"><div class="body">{% endif %}
+                {{ sidebar }}
+            {% if page.extra.sidebar_wrap %}</div></div>{% endif %}
+        {% endif %}
+        {% sidebar_lower %}
+    {% endblock %}
+{% endifequal %}
+
+
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/pagesize.html b/forum/modules/template_loader.py/forum/skins/default/templates/pagesize.html
new file mode 100644 (file)
index 0000000..5037f1f
--- /dev/null
@@ -0,0 +1,27 @@
+<!-- template pagesize.html -->
+{% spaceless %}
+{% load i18n %}
+{% if is_paginated %}
+<div class="paginator">
+    <span class="text">{% trans "posts per page" %}</span>
+    {% ifequal pagesize 10 %}
+        <span class="curr">10</span>
+    {% else %}
+        <span class="page"><a href="{{base_url}}pagesize=10">10</a></span>
+    {% endifequal %}
+    
+    {% ifequal pagesize 30 %}
+        <span class="curr">30</span>
+    {% else %}
+        <span class="page"><a href="{{base_url}}pagesize=30">30</a></span>
+    {% endifequal %}
+    
+    {% ifequal pagesize 50 %}
+        <span class="curr">50</span>
+    {% else %}
+        <span class="page"><a href="{{base_url}}pagesize=50">50</a></span>
+    {% endifequal %}
+</div> 
+{% endif %}
+{% endspaceless %}
+<!-- end template pagesize.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/paginator.html b/forum/modules/template_loader.py/forum/skins/default/templates/paginator.html
new file mode 100644 (file)
index 0000000..2fba542
--- /dev/null
@@ -0,0 +1,38 @@
+<!-- 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 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>
+       {% endfor %}
+       ...
+{% endif %}
+{% for num in page_numbers %}
+  {% ifequal num page %}
+    {% ifequal pages 1 %}
+    {% else %}
+    <span class="curr" title="{% trans "current page" %}">{{ num }}</span>
+    {% endifequal %}
+  {% else %}
+       <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="{% 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="{% trans "next page" %}">{% trans "next page" %} &raquo;</a></span>{% endif %}
+</div> 
+{% endif %}
+{% endspaceless %}
+<!-- end paginator.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/paginator/page_numbers.html b/forum/modules/template_loader.py/forum/skins/default/templates/paginator/page_numbers.html
new file mode 100644 (file)
index 0000000..abe021d
--- /dev/null
@@ -0,0 +1,25 @@
+{% spaceless %}
+{% load i18n %}
+
+<p class="paginator">
+    {% if has_previous %}
+        <span class="prev"><a href="{{ previous_url }}" title="{% trans "previous" %}">&laquo; {% trans "previous" %}</a></span>
+    {% endif %}
+    {% for range in page_numbers %}
+        {% if range %}
+            {% for num, url in range %}
+                {% ifequal num current %}
+                    <span class="curr this_page">{{ num }}</span>
+                {% else %}
+                     <a class="page" href="{{ url }}" >{{ num }}</a>
+                {% endifequal %}
+            {% endfor %}
+        {% else %}
+          ...
+        {% endif %}
+    {% endfor %}
+    {% if has_next %}
+        <span class="next"><a href="{{ next_url }}" title="{% trans "next page" %}">{% trans "next page" %} &raquo;</a></span>    
+    {% endif %}
+</p>
+{% endspaceless %}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/paginator/page_sizes.html b/forum/modules/template_loader.py/forum/skins/default/templates/paginator/page_sizes.html
new file mode 100644 (file)
index 0000000..f0859b5
--- /dev/null
@@ -0,0 +1,13 @@
+{% spaceless %}
+{% load i18n %}
+<div class="paginator">
+    <span class="text">{% trans "posts per page" %}</span>
+    {% for size, url in sizes %}
+        {% ifequal size current %}
+            <span class="curr">{{ size }}</span>
+        {% else %}
+            <span class="page"><a href="{{ url }}">{{ size }}</a></span>
+        {% endifequal %}
+    {% endfor %}
+</div>
+{% endspaceless %}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/paginator/sort_tabs.html b/forum/modules/template_loader.py/forum/skins/default/templates/paginator/sort_tabs.html
new file mode 100644 (file)
index 0000000..a0662a9
--- /dev/null
@@ -0,0 +1,13 @@
+{% load i18n %}
+{% spaceless %}
+<div class="tabsA">
+    {% for name, label, url, descr in sorts %}
+        <a href="{{ url }}"{% ifequal current name %} class="on"{% endifequal %} title="{{ descr }}">{{ label }}</a>
+    {% endfor %}
+    {% comment %}
+    <span class="sticky-sort-tabs">
+        <input title="{% trans "Check to make the sort order sticky" %}" type="checkbox" checked="{% if sticky %}checked{% endif %}" />
+    </span>
+    {% endcomment %}
+</div>
+{% endspaceless %}
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/privacy.html b/forum/modules/template_loader.py/forum/skins/default/templates/privacy.html
new file mode 100644 (file)
index 0000000..e66086d
--- /dev/null
@@ -0,0 +1,42 @@
+{% extends "base_content.html" %}
+<!-- privacy.html -->
+{% load extra_tags %}
+{% load i18n %}
+{% load humanize %}
+{% block title %}{% spaceless %}{% trans "Privacy policy" %}{% endspaceless %}{% endblock %}
+{% block forejs %}
+{% endblock %}
+{% block content %}
+<div class="headNormal">
+       {% trans "Privacy policy" %}
+</div>
+<div id="main-body" style="width:100%">
+    <p>
+               {% trans "general message about privacy" %}
+    </p>
+    
+        <h3 class="subtitle">{% trans "Site Visitors" %}</h3>
+    <p>    
+       {% trans "what technical information is collected about visitors" %}
+    </p>
+    
+        <h3 class="subtitle">{% trans "Personal Information" %}</h3>
+    <p>   
+               {% trans "details on personal information policies" %}
+    </p>
+   
+        <h3 class="subtitle">{% trans "Other Services" %}</h3>
+     <p>   
+        {% trans "details on sharing data with third parties" %}
+    </p>
+    
+        <h3 class="subtitle">Cookies</h3>
+    <p>
+               {% trans "cookie policy details" %}
+    </p>
+        <h3 class="subtitle">{% trans "Policy Changes" %}</h3>
+    <p>{% trans "how privacy policies can be changed" %}
+    </p>
+</div>
+{% endblock %}
+<!-- end privacy.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/question.html b/forum/modules/template_loader.py/forum/skins/default/templates/question.html
new file mode 100644 (file)
index 0000000..c6c4cde
--- /dev/null
@@ -0,0 +1,322 @@
+{% extends "base.html" %}\r
+<!-- question.html -->\r
+{% load node_tags %}\r
+{% load extra_tags %}\r
+{% load extra_filters %}\r
+{% load general_sidebar_tags %}\r
+{% load smart_if %}\r
+{% load humanize %}\r
+{% load i18n %}\r
+{% load cache %}\r
+{% block metadescription %}{{ question.meta_description }}{% endblock %}\r
+{% block metakeywords %}{{question.tagname_meta_generator}}{% endblock %}\r
+{% block meta %}\r
+        <link rel="canonical" href="{{settings.APP_BASE_URL}}{{question.get_absolute_url}}" />\r
+        <link rel="alternate" type="application/rss+xml" title="RSS" href="{{ question.get_absolute_url }}?type=rss">\r
+{% endblock %}\r
+{% block title %}{% spaceless %}{{ question.headline }}{% endspaceless %}{% endblock %}\r
+{% block forejs %}\r
+        {% if not question.nis.closed %}\r
+        <script type='text/javascript' src='{% media  "/media/js/osqa.question.js" %}'></script>\r
+        <script type='text/javascript' src='{% media  "/media/js/wmd/showdown.js" %}'></script>\r
+        <script type='text/javascript' src='{% media  "/media/js/wmd/wmd.js" %}'></script>\r
+        <link rel="stylesheet" type="text/css" href="{% media  "/media/js/wmd/wmd.css" %}" />\r
+        {% endif %}\r
+\r
+        <script type="text/javascript">\r
+        $().ready(function(){\r
+            $("#nav_questions").attr('className',"on");\r
+            var answer_sort_tab = "{{ tab_id }}";\r
+\r
+            if (answer_sort_tab) {\r
+                $("#" + answer_sort_tab).attr('className',"on");\r
+            }\r
+\r
+            $('#editor').TextAreaResizer();\r
+\r
+            //toggle preview of editor\r
+            var display = true;\r
+            var txt = "[{% trans "hide preview" %}]";\r
+            $('#pre-collapse').text(txt);\r
+            $('#pre-collapse').bind('click', function(){\r
+                txt = display ? "[{% trans "show preview" %}]" : "[{% trans "hide preview" %}]";\r
+                display = !display;\r
+                $('#previewer').toggle();\r
+                $('#pre-collapse').text(txt);\r
+            });\r
+        });\r
+\r
+        function submitClicked(e, f) {\r
+            if(!(browserTester('chrome') || browserTester('safari'))) {\r
+                $("input.submit")[0].disabled=true;\r
+            }\r
+            window.removeEventListener('beforeunload', beforeUnload, true);\r
+            if (f) {\r
+                f.submit();\r
+            }\r
+        }\r
+\r
+        function beforeUnload(e) {\r
+\r
+            if($("textarea#editor")[0].value != "") {\r
+                return yourWorkWillBeLost(e);\r
+            }\r
+\r
+            var commentBoxes = $("textarea.commentBox");\r
+            for(var index = 0; index < commentBoxes.length; index++) {\r
+                if(commentBoxes[index].value != "") {\r
+                    return yourWorkWillBeLost(e);\r
+                }\r
+            }\r
+        }\r
+        window.addEventListener('beforeunload', beforeUnload, true);\r
+        </script>\r
+        <noscript>\r
+            <style>\r
+                .comment.not_top_scorer {\r
+                    display: block;\r
+                }\r
+                .comment-form-container {\r
+                    display: block;\r
+                }\r
+                .div.comment-tools {\r
+                    display: none;\r
+                }\r
+            </style>\r
+        </noscript>\r
+{% endblock %}\r
+        \r
+{% block content %}\r
+<div class="headNormal">\r
+    <h1><a href="{{ question.get_absolute_url }}">{{ question.headline }}</a></h1>\r
+</div>\r
+<div id="main-body" class="">\r
+    <div id="askform">\r
+            <table style="width:100%;" id="question-table" {% post_classes question %}>\r
+                <tr>\r
+                    <td style="width:30px;vertical-align:top">\r
+                        <div class="vote-buttons">\r
+                            {% vote_buttons question request.user %}\r
+                            {% favorite_mark question request.user %}                            \r
+                        </div>\r
+                    </td>\r
+                    <td>\r
+                        <div id="item-right">\r
+                            <div class="question-body">\r
+                                {{ question.html|safe }}\r
+                            </div>\r
+                            <div id="question-tags" class="tags-container tags">\r
+                                {% for tag in question.tagname_list %}\r
+                                    <a href="{% url tag_questions tag|urlencode %}" class="post-tag tag-link-{{ tag }}"\r
+                                        title="{% blocktrans with tag as tagname %}see questions tagged '{{ tagname }}'{% endblocktrans %}" rel="tag">{{ tag }}</a>\r
+                                {% endfor %}\r
+                            </div>\r
+                            <div id="question-controls" class="post-controls">                            \r
+                                {% post_controls question request.user %}\r
+                                {% wiki_symbol request.user question %}\r
+                            </div>\r
+                            <div class="post-update-info-container">\r
+                                    {% contributors_info question %}\r
+                            </div>\r
+                            {% comments question request.user %}\r
+                        </div>\r
+                        \r
+                    </td>\r
+                </tr>\r
+            </table>\r
+            {% if question.nis.closed %}\r
+            <div class="question-status" style="margin-bottom:15px">\r
+            <h3>\r
+                {% blocktrans with question.nstate.closed.extra as close_reason %}The question has been closed for the following reason "{{ close_reason }}" by{% endblocktrans %}\r
+                <a href="{{ question.nstate.closed.by.get_profile_url }}">{{ question.nstate.closed.by.username }}</a>\r
+                 {% diff_date question.nstate.closed.at %}\r
+            </h3>\r
+            </div>\r
+            {% endif %}\r
+            {% if answers %}\r
+                <hr/>\r
+                <div class="tabBar">\r
+                    <a name="sort-top"></a>\r
+                    <div class="headQuestions">\r
+                    {% blocktrans count answers.paginator.count as counter %}One Answer:{% plural %}{{counter}} Answers:{% endblocktrans %}\r
+                    </div>\r
+                    {{ answers.paginator.sort_tabs }}\r
+                </div>\r
+                {{ answers.paginator.page_numbers }}\r
+  \r
+                {% for answer in answers.paginator.page %}\r
+                    <a name="{{ answer.id }}"></a>\r
+                    <div id="answer-container-{{ answer.id }}" class="answer {% post_classes answer %}">\r
+                        <table style="width:100%;">\r
+                            <tr>\r
+                                <td style="width:30px;vertical-align:top">\r
+                                    <div class="vote-buttons">\r
+                                        {% vote_buttons answer request.user %}\r
+                                        {% accept_button answer request.user %}\r
+                                    </div>\r
+                                </td>\r
+                                <td>\r
+                                    <div class="item-right">\r
+                                        <div class="answer-body">\r
+                                            {{ answer.html|safe }}\r
+                                        </div>\r
+                                        <div class="answer-controls post-controls">\r
+                                            {% post_controls answer request.user %}\r
+                                            {% wiki_symbol request.user answer %}\r
+                                        </div>\r
+                                        <div class="post-update-info-container">\r
+                                            {% contributors_info answer %}\r
+                                        </div>\r
+                                        {% comments answer request.user %}\r
+                                    </div>\r
+                                </td>\r
+                            </tr>\r
+                        </table>\r
+                    </div>\r
+                {% endfor %}\r
+                <div class="paginator-container-left">\r
+                    {{ answers.paginator.page_numbers }}\r
+                </div>\r
+            {% endif %}\r
+        <form id="fmanswer" action="{% url answer question.id %}" method="post">\r
+            <div style="clear:both">\r
+            </div>\r
+            \r
+            {% if not question.closed %}\r
+                <div style="padding:10px 0 0 0;">\r
+                    {% spaceless %}\r
+                    <div class="headNormal">\r
+                        {% if answers %}\r
+                            {% trans "Your answer" %}\r
+                        {% else %}\r
+                            {% trans "Be the first one to answer this question!" %}\r
+                        {% endif %}\r
+                    </div>\r
+                    {% endspaceless %}\r
+                </div>\r
+                {% comment %}\r
+                {% if not request.user.is_authenticated %}\r
+                    <div class="message">{% trans "You can answer anonymously and then login." %}</div>\r
+                {% else %}\r
+                    <p class="message">\r
+                        {% ifequal request.user question.author  %}\r
+                            {% trans "Answer your own question only to give an answer." %}\r
+                        {% else %}\r
+                            {% trans "Please only give an answer, no discussions." %}\r
+                        {% endifequal %}\r
+                        {% if not request.user.email_valid_and_can_answer %}\r
+                            {% blocktrans %}Remember, your answer will not be published until you validate your email.{% endblocktrans %}\r
+                            <a href="{% url send_validation_email %}">{% trans "Send me a validation link." %}</a>\r
+                        {% endif %}\r
+                    </p>\r
+                {% endif %}\r
+                {% endcomment %}\r
+\r
+                <div id="description" class="" >\r
+                    <div id="wmd-button-bar" class="wmd-panel"></div>\r
+                    {{ answer.text }}\r
+                    <div class="preview-toggle">\r
+                        <table width="100%">\r
+                            <tr>\r
+                                <td>\r
+                                    <span id="pre-collapse" \r
+                                        title="{% trans "Toggle the real time Markdown editor preview" %}">\r
+                                            {% trans "toggle preview" %}\r
+                                    </span>\r
+                                </td>\r
+                                <td style="text-align: right;" id="editor-metrics"></td>\r
+                                {% if settings.WIKI_ON %}\r
+                                <td style="text-align:right;">\r
+                                    {{ answer.wiki }} \r
+                                    <span style="font-weight:normal;cursor:help" \r
+                                        title="{{answer.wiki.help_text}}">\r
+                                            {{ answer.wiki.label_tag }} \r
+                                    </span>\r
+                                </td>\r
+                                {% endif %}\r
+                            </tr>\r
+                        \r
+                        </table>  \r
+                    </div>\r
+                    {{ answer.text.errors }}\r
+                    <div id="previewer" class="wmd-preview"></div>\r
+                </div>\r
+\r
+                   {% if answer.recaptcha %}\r
+                   <div class="question-captcha" style="float: left;">\r
+                       {{ answer.recaptcha.errors }}\r
+                       {{ answer.recaptcha }}\r
+                   </div>\r
+                   <div class="clear"></div>\r
+                   {% endif %}\r
+                \r
+                <p><span class="form-error"></span></p>\r
+                <input type="button"\r
+                    {% if user.is_anonymous %}\r
+                        value="{% trans "Login/Signup to Post Your Answer" %}" \r
+                    {% else %}\r
+                        {% if user == question.author %}\r
+                        value="{% trans "Answer Your Own Question" %}" \r
+                        {% else %}\r
+                        value="{% trans "Answer the question" %}" \r
+                        {% endif %}\r
+                    {% endif %}\r
+                    class="submit" style="float:left" onclick="submitClicked(event, this.form)"/>\r
+            {% endif %}\r
+        </form>\r
+    </div>\r
+</div>\r
+{% endblock %}\r
+\r
+{% block sidebar %}\r
+<div class="boxC" id="subscription_box">\r
+    {% include "subscription_status.html" %}\r
+</div>\r
+\r
+{% markdown_help %}\r
+\r
+{% sidebar_upper %}\r
+\r
+{% cache 60 questions_tags settings.APP_URL question.id %}\r
+<div class="boxC">\r
+    <p>\r
+               {% trans "Question tags" %}:\r
+    </p>\r
+    <p class="tags" >\r
+        {% for tag in question.tags.all %}\r
+               <a href="{% url tag_questions tag.name|urlencode %}"\r
+            class="tag-link-{{ tag.name }}"\r
+                       title="{% trans "see questions tagged"%}'{{tag.name}}'{% trans "using tags" %}"\r
+                       rel="tag">{{ tag.name }}</a> <span class="tag-number">&#215;{{ tag.used_count|intcomma }}</span><br/>\r
+        {% endfor %}\r
+    </p>\r
+    <p>\r
+        {% trans "question asked" %}: <strong title="{{ question.added_at }}">{% diff_date question.added_at %}</strong>\r
+    </p>\r
+    <p> \r
+       {% trans "question was seen" %}: <strong>{{ question.view_count|intcomma }} {% trans "times" %}</strong>\r
+    </p>\r
+    <p> \r
+        {% trans "last updated" %}: <strong title="{{ question.last_activity_at }}">{% diff_date question.last_activity_at %}</strong>\r
+    </p>\r
+</div>\r
+{% endcache %}\r
+{% sidebar_lower %}\r
+<div class="boxC">\r
+    <h3 class="subtitle">{% trans "Related questions" %}</h3>\r
+    <div class="questions-related">\r
+\r
+        {% for question in similar_questions %}\r
+        <p>\r
+            <a href="{{ question.get_absolute_url }}">{{ question.headline }}</a>\r
+        </p>\r
+        {% endfor %}\r
+\r
+    </div>\r
+</div>\r
+\r
+{% endblock %}\r
+\r
+{% block endjs %}\r
+{% endblock %}\r
+<!-- end question.html -->\r
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/question_edit.html b/forum/modules/template_loader.py/forum/skins/default/templates/question_edit.html
new file mode 100644 (file)
index 0000000..9d7a6cd
--- /dev/null
@@ -0,0 +1,166 @@
+{% extends "base.html" %}
+<!-- question_edit.html -->
+{% load i18n %}
+{% load extra_tags %}
+{% block title %}{% spaceless %}{% trans "Edit question" %}{% endspaceless %}{% endblock %}
+{% block forejs %}
+        <script type='text/javascript' src='{% media  "/media/js/wmd/showdown.js" %}'></script>
+        <script type='text/javascript' src='{% media  "/media/js/wmd/wmd.js" %}'></script>
+        <link rel="stylesheet" type="text/css" href="{% media  "/media/js/wmd/wmd.css" %}" />
+        <script type="text/javascript">
+               //todo move javascript out        
+        $().ready(function(){
+            $("#nav_questions").attr('className',"on");
+            $('#editor').TextAreaResizer();
+            
+
+            //toggle preview of editor
+            var display = true;
+            var txt = "[{% trans "hide preview" %}]";
+            $('#pre-collapse').text(txt);
+            $('#pre-collapse').bind('click', function(){
+                txt = display ? "[{% trans "show preview" %}]" : "[{% trans "hide preview" %}]";
+                display = !display;
+                $('#previewer').toggle();
+                $('#pre-collapse').text(txt);
+            });
+            
+            //Tags autocomplete action
+               $("#id_tags").autocomplete("/matching_tags/", {
+                       matchContains: true,
+                max: 20,
+                multiple: true,
+                multipleSeparator: " ",
+                highlightItem: true,
+                scroll: true,
+                scrollHeight: 300,
+                       /*formatItem: function(row, i, max) {
+                               return row.n + " ("+ row.c +")";
+                       },
+                formatResult: function(row, i, max){
+                    return row.n;
+                }*/
+                formatItem: function(row, i, max, value) {
+                    return row[1] + " (" + row[2] + ")";
+                },
+
+                formatResult: function(row, i, max, value){
+                    return row[1];
+                }
+                
+            });         
+
+            $('#id_revision').unbind().change(function(){
+                $("#select_revision").click();
+            });
+
+            init = $("textarea#editor")[0].value;
+
+            title = $("input#id_title")[0].value;
+            body = $("textarea#editor")[0].value;
+            tag = $("input#id_tags")[0].value;
+        });
+
+        function submitClicked(e, f) {
+            if(!(browserTester('chrome') || browserTester('safari'))) {
+                $("input.submit")[0].disabled=true;
+                $("input.submit")[1].disabled=true;
+            }
+            window.removeEventListener('beforeunload', beforeUnload, true);
+            if (f) {
+                f.submit();
+            }
+        }
+
+        function beforeUnload(e) {
+            if($("input#id_title")[0].value != title || $("textarea#editor")[0].value != body || $("input#id_tags")[0].value != tag) {
+                 return yourWorkWillBeLost(e);
+            }
+        }
+        window.addEventListener('beforeunload', beforeUnload, true);
+
+        var init = "";
+        var title = "";
+        var body = "";
+        var tag = "";
+        </script>
+{% endblock %}
+        
+{% block content %}
+<div id="main-bar" class="headNormal">
+    {% trans "Edit question" %} [<a href="{{ question.get_absolute_url }}">{% trans "back" %}</a>]
+</div>
+<div id="main-body" class="ask-body">
+    <div id="askform">
+        <form id="fmedit" action="{% url edit_question question.id %}" method="post" >
+            <label for="id_revision" ><strong>{% trans "revision" %}:</strong></label> <br/> 
+            {% if revision_form.revision.errors %}{{ revision_form.revision.errors.as_ul }}{% endif %}
+            <div style="vertical-align:middle">
+            {{ revision_form.revision }} <input type="submit" style="display:none" id="select_revision" name="select_revision" 
+                                                                                       value="{% trans "select revision"%}">
+            </div> 
+            <div class="form-item">
+                <label for="id_title" ><strong>{{ form.title.label_tag }}:</strong></label> <span class="form-error"></span><br/> 
+                {{ form.title }} {{ form.title.errors }}  
+                <div class="title-desc">
+                    {{ form.title.help_text }}
+                </div>     
+            </div>
+            <div class="form-item">
+                <div id="wmd-button-bar" class="wmd-panel"></div>
+                {{ form.text }}
+                <span class="form-error"></span>
+                <div class="preview-toggle">
+                    <table width="100%">
+                        <tr>
+                            <td>
+                                <span id="pre-collapse" title="{% trans "Toggle the real time Markdown editor preview" %}">{% trans "toggle preview" %}</span>
+                            </td>
+                            <td style="text-align: right;" id="editor-metrics"></td>
+                            {% if settings.WIKI_ON %}
+                            <td style="text-align:right;">
+                                {{ form.wiki }} <span style="color:#000;cursor:help" title="{{form.wiki.help_text}}">{{ form.wiki.label_tag }} </span>
+                            </td>
+                            {% endif %}
+                        </tr>
+                    
+                    </table>   
+                </div>
+                <div id="previewer" class="wmd-preview"></div>
+            </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>
+            <strong>{{ form.summary.label_tag }}</strong> <br/>
+            {{ form.summary }}  {{ form.summary.errors }}
+            <div class="title-desc">
+                {{ form.summary.help_text }}
+            </div>
+            
+            {% if form.recaptcha %}
+            <div class="question-captcha" style="float: left">
+               {{ form.recaptcha.errors }}
+               {{ form.recaptcha }}
+            </div>
+            <div class="clear"></div>
+            {% endif %}
+            
+            <div class="error" ></div>
+            <input type="button" value="{% trans "Save edit" %}" class="submit" onclick="submitClicked(event, this.form)" />
+            <input type="button" value="{% trans "Cancel" %}" class="submit" onclick="submitClicked(event, null); history.back(-1);" />
+        </form>
+    </div>
+</div>
+{% endblock %}
+
+{% block sidebar %}
+{% include "question_edit_tips.html" %}
+{% endblock %}
+
+{% block endjs %}
+{% endblock %}
+<!-- end question_edit.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/question_edit_tips.html b/forum/modules/template_loader.py/forum/skins/default/templates/question_edit_tips.html
new file mode 100644 (file)
index 0000000..d54deef
--- /dev/null
@@ -0,0 +1,48 @@
+<!-- question_edit_tips.html -->
+{% load i18n general_sidebar_tags %}
+<div class="boxC" id="title_side_bar">
+    <p class="subtitle darkred">{% trans "Title Tips" %}</p>
+    <div>
+        <ul class="list-item">
+            <li>
+            <b>
+                {% blocktrans with settings.APP_SHORT_NAME as app_title %}
+                ask a question relevant to the {{ app_title }} community 
+                {% endblocktrans %}
+            </b>
+            </li>
+            <li>
+                {% trans "please try provide enough details" %}
+            </li>
+            <li>
+                               {% trans "be clear and concise" %}
+            </li>
+        </ul>
+        <p class='info-box-follow-up-links'>
+            <a href="{% url faq %}" target="_blank" title="{% trans "see frequently asked questions" %}">{% trans "faq" %} &raquo;</a>
+        </p>
+    </div>
+</div>
+
+{% markdown_help %}
+
+<div class="boxC" id="tags_side_bar" align="left">
+    <p class="subtitle darkred">{% trans "What Are Tags" %}</p>
+    <ul class="list-item">
+        <li>
+            {% trans "Tags are words that will tell others what this question is about." %}
+        </li>
+        <li>
+            {% trans "They will help other find your question." %}
+        </li>
+        <li>
+            {% blocktrans with settings.FORM_MAX_NUMBER_OF_TAGS as max_number_of_tags and settings.FORM_MIN_NUMBER_OF_TAGS as min_number_of_tags %}
+                A question can have up to {{max_number_of_tags}} tags, but it must have at least {{min_number_of_tags}}.
+            {% endblocktrans %}
+        </li>
+    </ul>
+</div>
+
+
+<!-- end question_edit_tips.html  -->
+                                  
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/question_list/count.html b/forum/modules/template_loader.py/forum/skins/default/templates/question_list/count.html
new file mode 100644 (file)
index 0000000..dbb45eb
--- /dev/null
@@ -0,0 +1,26 @@
+{% spaceless %}\r
+{% load i18n humanize extra_tags %}\r
+{% declare %}\r
+    answer_count = questions.children_count('answer')\r
+{% enddeclare %}\r
+\r
+<div class="boxC">\r
+    <div class="questions-count">\r
+        {{ questions.paginator.count }}<span style="color:black;font-size:14px;margin-left:5px">{{ list_description }}</span>\r
+    </div>\r
+\r
+\r
+    {% if answer_count %}\r
+    <div class="questions-count">\r
+        {{ answer_count }}<span style="color:black;font-size:14px;margin-left:5px">{% trans "answers" %}</span>\r
+    </div>\r
+\r
+    {% endif %}\r
+\r
+    <div>\r
+        <p class="nomargin">\r
+            {{ questions.paginator.sort_description }}\r
+        </p>\r
+    </div>\r
+</div>\r
+{% endspaceless %}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/question_list/item.html b/forum/modules/template_loader.py/forum/skins/default/templates/question_list/item.html
new file mode 100644 (file)
index 0000000..4eb3c3b
--- /dev/null
@@ -0,0 +1,35 @@
+{% load i18n humanize extra_filters extra_tags user_tags %}\r
+<div class="short-summary">\r
+    <div class="counts">{% if favorite_count %}\r
+        <div class="favorites">\r
+            <span class="favorite-mark{% if question.favourite_count %} on{% endif %}"></span>\r
+            <div class="item-count">{{question.favourite_count|intcomma}}</div>\r
+        </div>\r
+        {% endif %}\r
+        <div class="votes">\r
+            <div class="item-count">{{question.score|intcomma}}</div>\r
+            <div>{% ifequal question.score 1 %}{% trans "vote" %}{% else %}{% trans "votes" %}{% endifequal %}</div>\r
+        </div >\r
+        <div {% if question.accepted_count %}title="{% trans "this question has an accepted answer" %}"{% endif %} class="status {% if question.accepted_count %}answered-accepted{% endif %} {% ifequal question.answer_count 0 %}unanswered{% endifequal %}{% ifnotequal question.answer_count 0 %}answered{% endifnotequal %}">\r
+            <div class="item-count">{{question.answer_count|intcomma}}</div>\r
+            <div>{% ifequal question.answer_count 1 %}{% trans "answer" %}{% else %}{% trans "answers" %}{% endifequal %}</div>\r
+        </div>\r
+        <div class="views">\r
+             <div class="item-count">{{question.view_count|decorated_int|safe}}</div>\r
+             <div>{% ifequal question.view_count 1 %}{% trans "view" %}{% else %}{% trans "views" %}{% endifequal %}</div>\r
+        </div>\r
+    </div>\r
+\r
+    <div class="question-summary-wrapper">\r
+        <h2><a title="{{ question.summary }}" href="{{ question.get_absolute_url }}">{{question.headline}}</a></h2>\r
+        <div class="userinfo">\r
+            <span class="relativetime" title="{{question.last_activity_at}}">{% diff_date question.last_activity_at %}</span>\r
+            {% if question.last_activity_by %}{% user_signature question.last_activity_by signature_type %}{% endif %}\r
+        </div>\r
+\r
+        <div class="tags">{% for tag in question.tagname_list %}\r
+            <a class="tag-link-{{ tag }}" href="{% url tag_questions tag|urlencode %}" title="{% trans "see questions tagged" %} '{{ tag }}'" rel="tag">{{ tag }}</a>{% endfor %}\r
+        </div>\r
+    </div>\r
+\r
+</div>
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/question_list/related_tags.html b/forum/modules/template_loader.py/forum/skins/default/templates/question_list/related_tags.html
new file mode 100644 (file)
index 0000000..6ec2a75
--- /dev/null
@@ -0,0 +1,15 @@
+{% load i18n %}\r
+{% load humanize %}\r
+\r
+{% if tags %}\r
+    <div class="boxC">\r
+        <h3 class="subtitle">{% trans "Related tags" %}</h3>\r
+        <div class="tags" id="recent-tags">\r
+            {% for tag in tags %}\r
+                <a rel="tag" class="tag-link-{{ tag.name }}" title="{% blocktrans with tag.name as tag_name %}see questions tagged '{{ tag_name }}'{% endblocktrans %}"  href="{% url tag_questions tag.name|urlencode %}">{{ tag.name }}</a>\r
+                <span class="tag-number">&#215; {{ tag.used_count|intcomma }}</span>\r
+                <br />\r
+            {% endfor %}\r
+        </div>\r
+    </div>\r
+{% endif %}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/question_list/sort_tabs.html b/forum/modules/template_loader.py/forum/skins/default/templates/question_list/sort_tabs.html
new file mode 100644 (file)
index 0000000..eff0408
--- /dev/null
@@ -0,0 +1,8 @@
+{% load i18n %}\r
+\r
+<div class="tabsA">\r
+    <a id="active" href="{{ base_url }}active"{% ifequal current "active" %} class="on"{% endifequal %} title="{% trans "most recently updated questions" %}">{% trans "active" %}</a>\r
+    <a id="latest" href="{{ base_url }}latest"{% ifequal current "latest" %} class="on"{% endifequal %} title="{% trans "most recently asked questions" %}">{% trans "newest" %}</a>\r
+    <a id="hottest" href="{{ base_url }}hottest"{% ifequal current "hottest" %} class="on"{% endifequal %} title="{% trans "hottest questions" %}">{% trans "hottest" %}</a>\r
+    <a id="mostvoted" href="{{ base_url }}mostvoted"{% ifequal current "mostvoted" %} class="on"{% endifequal %} title="{% trans "most voted questions" %}">{% trans "most voted" %}</a>\r
+</div>\r
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/question_list/subscription_item.html b/forum/modules/template_loader.py/forum/skins/default/templates/question_list/subscription_item.html
new file mode 100644 (file)
index 0000000..3f1f688
--- /dev/null
@@ -0,0 +1,10 @@
+{% load i18n humanize extra_filters extra_tags user_tags %}
+<div class="subscription_summary">
+    <div style="height:100%"><a class="sidebar_button subscription_unsubscribe_button" href="{% url subscribe id=subscription.question.id user=subscription.user.id %}">
+        {% trans "Unsubscribe" %}
+    </a></div>
+
+    <div class="subscription_title"><a title="{{ question.summary }}" href="{{ question.get_absolute_url }}">{{question.headline}}</a></div>
+    <div class="subscription_details"><span class="relativetime" title="{{subscription.last_view}}">{% trans "Last checked" %} {% diff_date subscription.last_view %}</span></div>
+</div>
+
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/question_list/tag_selector.html b/forum/modules/template_loader.py/forum/skins/default/templates/question_list/tag_selector.html
new file mode 100644 (file)
index 0000000..f507d64
--- /dev/null
@@ -0,0 +1,49 @@
+{% load i18n %}
+{% load extra_tags %}
+
+{% if user_authenticated %}
+<div id="tagSelector" class="boxC">
+       <h3 class="subtitle">{% trans "Interesting tags" %}</h3>
+    <div class="tags interesting marked-tags">
+    {% for tag_name in interesting_tag_names %}
+        {% spaceless %}
+        <span class="deletable-tag" id="interesting-tag-{{tag_name}}">
+            <a rel="tag" 
+                class="tag-link-{{ tag_name }}"
+                title="{% blocktrans with tag as tagname %}see questions tagged '{{ tag_name }}'{% endblocktrans %}"
+                href="{% url tag_questions tag_name|urlencode %}">{{tag_name}}</a>
+            <img class="delete-icon" 
+                src="{% media  "/media/images/close-small-dark.png" %}"
+                title="{% blocktrans %}remove '{{tag_name}}' from the list of interesting tags{% endblocktrans %}"/>
+        </span>
+        {% endspaceless %}
+    {% endfor %}
+    </div>
+    <input id="interestingTagInput" autocomplete="off" type="text"/>
+    <input id="interestingTagAdd" type="submit" value="{% trans "Add" %}"/>
+       <h3 class="subtitle">{% trans "Ignored tags" %}</h3>
+    <div class="tags ignored marked-tags">
+    {% for tag_name in ignored_tag_names %}
+        {% spaceless %}
+        <span class="deletable-tag" id="ignored-tag-{{tag_name}}">
+            <a rel="tag" 
+                class="tag-link-{{ tag_name }}"
+                title="{% blocktrans with tag as tagname %}see questions tagged '{{ tag_name }}'{% endblocktrans %}"
+                href="{% url tag_questions tag_name|urlencode %}">{{tag_name}}</a>
+            <img class="delete-icon" 
+                src="{% media  "/media/images/close-small-dark.png" %}"
+                title="{% blocktrans %}remove '{{tag_name}}' from the list of ignored tags{% endblocktrans %}"/>
+        </span>
+        {% endspaceless %}
+    {% endfor %}
+    </div>
+    <input id="ignoredTagInput" autocomplete="off" type="text"/>
+    <input id="ignoredTagAdd" type="submit" value="{% trans "Add" %}"/>
+    {% comment %}
+    <p id="hideIgnoredTagsControl">
+    <input id="hideIgnoredTagsCb" type="checkbox" {% if request.user.hide_ignored_questions %}checked="checked"{% endif %} />
+    <label id="hideIgnoredTagsLabel" for="hideIgnoredTagsCb">{% trans "keep ignored questions hidden" %}</label>
+    <p>
+    {% endcomment %}
+</div>
+{% endif %}
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/question_list/title.html b/forum/modules/template_loader.py/forum/skins/default/templates/question_list/title.html
new file mode 100644 (file)
index 0000000..bb6268f
--- /dev/null
@@ -0,0 +1,25 @@
+{% load i18n %}\r
+\r
+<div class="headQuestions">\r
+    {% if searchtag %}\r
+        {% trans "Found by tags" %}\r
+    {% else %}\r
+        {% if searchtitle %}\r
+            {% if settings.USE_SPHINX_SEARCH %}\r
+                {% trans "Search results" %}\r
+            {% else %}\r
+                {% trans "Found by title" %}\r
+            {% endif %}\r
+        {% else %}\r
+            {% if is_unanswered %}\r
+                {% trans "Unanswered questions" %}\r
+            {% else %}\r
+                {% if page_title %}\r
+                    {% trans page_title %}\r
+                {% else %}\r
+                    {% trans "All Questions" %}\r
+                {% endif %}\r
+            {% endif %}\r
+        {% endif %}\r
+    {% endif %}\r
+</div>
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/question_retag.html b/forum/modules/template_loader.py/forum/skins/default/templates/question_retag.html
new file mode 100644 (file)
index 0000000..6ec1313
--- /dev/null
@@ -0,0 +1,106 @@
+{% extends "base.html" %}
+<!-- question_retag.html -->
+{% load extra_tags %}
+{% load i18n %}
+{% block title %}{% spaceless %}{% trans "Change tags" %}{% endspaceless %}{% endblock %}
+{% block forejs %}
+        <script type="text/javascript">
+        
+        $().ready(function(){
+            $("#nav_questions").attr('className',"on");
+            //Tags autocomplete action
+               $("#id_tags").autocomplete("/matching_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;
+                } */
+                formatItem: function(row, i, max, value) {
+                    return row[1] + " (" + row[2] + ")";
+                },
+
+                formatResult: function(row, i, max, value){
+                    return row[0];
+                }
+                
+            });
+           
+             $("#fmretag").validate({
+                rules: {
+                               tags: {
+                                       required: true,
+                                       maxength: 105
+                               }
+                       },
+                messages: {
+                               tags: {
+                        required: "{% trans "tags are required" %}",
+                        {% blocktrans with settings.FORM_MAX_NUMBER_OF_TAGS as max_number_of_tags and settings.FORM_MAX_LENGTH_OF_TAG as max_length_of_tags %}
+                        maxlength: "up to {{max_number_of_tags}} tags, less than {{max_length_of_tags}} characters each"
+                        {% endblocktrans %}
+                    }
+                }
+                
+            });
+
+        });
+        </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.headline }}
+            </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>
+            <div class="error" ></div>
+            <input type="submit" value="{% trans "Save edit" %}" class="submit" />
+            <input type="button" value="{% trans "Cancel" %}" class="submit" onclick="history.back(-1);" />
+        </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 "tags help us keep Questions organized" %}
+        </li>
+        <li>
+            {% trans "tag editors receive special awards from the community" %}
+        </li>
+    </ul>
+    <p class='info-box-follow-up-links'>
+        <a href="{% url faq %}">faq &raquo;</a>
+    </p>
+</div>
+
+{% endblock %}
+
+{% block endjs %}
+{% endblock %}
+<!-- end question_retag.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/question_summary_list_roll.html b/forum/modules/template_loader.py/forum/skins/default/templates/question_summary_list_roll.html
new file mode 100644 (file)
index 0000000..b2ce45f
--- /dev/null
@@ -0,0 +1,55 @@
+    <div class="qstA">
+        <h2>
+            <a href="{{ question.get_absolute_url }}">{{ question.headline }}</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|decorated_int|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 and settings.WIKI_ON %}
+        <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 and settings.WIKI_ON %}
+        <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 class="tag-link-{{ tag }}" href="{% url tag_questions tag|urlencode %}" title="{% trans "see questions tagged" %}'{{ tag }}'{% trans "using tags" %}" rel="tag">{{ tag }}</a>
+        {% endfor %}
+        </div>
+    </div>
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/questions.html b/forum/modules/template_loader.py/forum/skins/default/templates/questions.html
new file mode 100644 (file)
index 0000000..3be2c97
--- /dev/null
@@ -0,0 +1,39 @@
+{% extends "base.html" %}\r
+<!-- questions.html -->\r
+{% load question_list_tags %}\r
+{% load i18n %}\r
+{% load extra_tags %}\r
+{% load general_sidebar_tags %}\r
+\r
+{% block title %}{% spaceless %}{{ page_title }}{% endspaceless %}{% endblock %}\r
+\r
+{% block meta %}\r
+    <link rel="alternate" type="application/rss+xml" title="RSS" href="{{ feed_url }}">\r
+{% endblock %}\r
+\r
+{% block content %}\r
+\r
+<div class="tabBar">\r
+    {% include "question_list/title.html" %}\r
+    <a class="feed-icon" style="background-image:url('{% media "media/images/feed-icon-small.png" %}');" href="{{ feed_url }}" title="{% trans "subscribe to question RSS feed" %}"></a>\r
+    {{ questions.paginator.sort_tabs }}\r
+</div>\r
+<div id="listA">{% for question in questions.paginator.page %}\r
+    {% question_list_item question %}\r
+{% endfor %}</div>\r
+{% endblock %}\r
+\r
+{% block tail %}\r
+    <div class="pager">{{ questions.paginator.page_numbers }}</div>\r
+    <div class="pagesize">{{ questions.paginator.page_sizes }}</div>\r
+{% endblock %}\r
+\r
+{% block sidebar %}\r
+    {% include "question_list/count.html" %}\r
+    {% sidebar_upper %}\r
+    {% tag_selector %}\r
+    {% sidebar_lower %}\r
+    {% question_list_related_tags questions.paginator.page %}\r
+\r
+{% endblock %}\r
+<!-- end questions.html -->\r
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/reopen.html b/forum/modules/template_loader.py/forum/skins/default/templates/reopen.html
new file mode 100644 (file)
index 0000000..cd0c37b
--- /dev/null
@@ -0,0 +1,37 @@
+{% extends "base_content.html" %}
+<!-- reopen.html -->
+{% load extra_tags %}
+{% load i18n %}
+{% load humanize %}
+{% block title %}{% spaceless %}{% trans "Reopen question" %}{% endspaceless %}{% endblock %}
+{% block forejs %}
+       <script type="text/javascript">
+        $().ready(function(){
+            $('#btBack').bind('click', function(){ history.back(); });
+        });
+        </script>
+{% endblock %}
+{% block content %}
+<div id="main-bar" class="headNormal">
+       {% trans "Reopen question" %}
+</div>
+<div id="main-body" style="width:100%">
+    <p>{% trans "Open the previously closed question" %}: <a href="{{ question.get_absolute_url }}"><span class="big">{{ question.headline }}</span></a>
+    
+    </p>   
+    <p><strong>{% trans "The question was closed for the following reason " %}"{{ question.get_close_reason_display }}"{% trans "reason - leave blank in english" %} <a href="{{ question.closed_by.get_profile_url }}">{{ question.closed_by.username }}</a> {% trans "on "%} {% diff_date question.closed_at %}<font class="darkred">{% trans "date closed" %}</font>
+        </strong>
+    </p>
+    
+    <form id="fmclose" action="{% url reopen question.id %}" method="post" >
+
+        <div id="" style="padding:20px 0 20px 0">
+            <input type="submit" value="{% trans "Reopen this question" %}" class="submit" />
+            <input id="btBack" type="button" value="{% trans "Cancel" %}"  class="submit"  />
+            
+        </div>
+        
+    </form>
+</div>
+{% endblock %}
+<!-- end reopen.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/revisions.html b/forum/modules/template_loader.py/forum/skins/default/templates/revisions.html
new file mode 100644 (file)
index 0000000..234b764
--- /dev/null
@@ -0,0 +1,78 @@
+{% extends "base_content.html" %}
+{% load node_tags %}
+{% load extra_tags %}
+{% load i18n %}
+{% load extra_filters %}
+{% load humanize %}
+{% block title %}{% spaceless %}{% trans "Revision history" %}{% endspaceless %}{% endblock %}
+{% block forejs %}
+    <script type="text/javascript">
+
+        $(document).ready(function() {
+            rev_bodies = $('div.rev-body');
+            if(rev_bodies.length > 0)toggleRev(rev_bodies.length);
+            if(rev_bodies.length > 1)toggleRev(rev_bodies.length-1);
+
+            for(var index = 0; index < rev_bodies.length; index++) {
+                rev_bodies.get(index);
+            }
+        });
+
+        function toggleRev(id) {
+            var rev_body = $('div#rev-body-' + id).get(0);
+            var rev_arrow = $('img#rev-arrow-' + id).get(0);
+            if (rev_body.style.display == "none") {
+                rev_body.style.display = "";
+                rev_arrow.src="{% media  "/media/images/expander-arrow-hide.gif" %}"
+            } else {
+                rev_body.style.display = "none";
+                rev_arrow.src="{% media  "/media/images/expander-arrow-show.gif" %}"
+            }
+        }
+        
+    </script>
+{% endblock %}
+        
+{% block content %}
+<div id="main-bar" class="headNormal">
+    {% trans "Revision history" %}[<a href="{{ post.get_absolute_url }}">{% trans "back" %}</a>]
+</div>
+<div id="main-body" class="">
+    <div id="revisions">
+    {% for revision in revisions %}
+      <div class="revision">
+        <div id="rev-header-{{ revision.inst.revision }}" class="header {% ifequal post.author revision.inst.author %}author{% endifequal %}">
+          <div class="header-controls">
+            <table width="100%">
+                <tr>
+                    <td width="20" style="vertical-align:middle"><img id="rev-arrow-{{ revision.inst.revision }}"
+                                                                      class="rev-arrow"
+                                                                      onclick="toggleRev({{ revision.inst.revision }})"
+                                                                      src="{% media  "/media/images/expander-arrow-show.gif" %}"
+                                                                      alt="{% trans "click to hide/show revision" %}"/>
+                    </td>
+                    <td width="30px" style="vertical-align:middle"><span class="revision-number" title="{% trans "revision" %} {{ revision.inst.revision }}">{{ revision.inst.revision }}</span></td>
+                    <td width="200px" style="vertical-align:middle">
+                        <div class="summary"><span>{{ revision.inst.summary }}</span></div>
+                    </td>
+                    <td align="right">
+                        <div class="revision-mark" >
+                            {% reviser_info revision.inst %}
+                        </div>
+                    </td>
+                </tr>
+                   
+            </table>
+          </div>
+        </div>
+        <div id="rev-body-{{ revision.inst.revision }}" class="diff body rev-body" style="display:none">
+            {{ revision.diff|safe }}
+        </div>
+      </div>
+    {% endfor %}
+    </div>
+</div>
+{% endblock %}
+
+{% block endjs %}
+{% endblock %}
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/search.html b/forum/modules/template_loader.py/forum/skins/default/templates/search.html
new file mode 100644 (file)
index 0000000..e413abd
--- /dev/null
@@ -0,0 +1,25 @@
+{% extends "base_content.html" %}
+
+{% load i18n %}
+
+{% block content %}
+<div id="main-bar" class="headNormal">
+       {% blocktrans with settings.APP_SHORT_NAME as app_name %}
+           Search in {{  app_name }}
+       {%  endblocktrans %}
+</div>
+<div id="main-body" style="text-align: center; height: 400px;">
+<form action="{% url search %}" method="get">
+    <div>
+        <input type="text" class="searchInput" value="{{ keywords }}" name="q" id="keywords" style="width: 600px" />
+        <input type="submit" name="Submit" value="{% trans "search" %}" class="searchBtn" />
+    </div>
+    <div class="options">
+        <input id="type-question" type="radio" value="question" name="t"
+            checked="checked" /><label for="type-question">{% trans "questions" %}</label>
+        <input id="type-tag" type="radio" value="tag" name="t" /><label for="type-tag">{% trans "tags" %}</label>
+        <input id="type-user" type="radio" value="user" name="t" /><label for="type-user">{% trans "users" %}</label>
+    </div>
+</form>
+</div>
+{% endblock %}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/sidebar/markdown_help.html b/forum/modules/template_loader.py/forum/skins/default/templates/sidebar/markdown_help.html
new file mode 100644 (file)
index 0000000..71dff87
--- /dev/null
@@ -0,0 +1,35 @@
+{% load i18n %}
+<div class="boxC" id="editor_side_bar">
+    <p class="subtitle darkred">{% trans "Markdown Basics" %}</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
+        </li>
+        <li>
+                       {% trans "to add a line break simply add two spaces to where you would like the new line to be." %}
+        </li>
+        <li>
+                       {% trans "basic HTML tags are also supported" %}
+        </li>
+    </ul>
+    <p class='info-box-follow-up-links'>
+        <a href="{% url markdown_help %}" target="_blank">{% trans "learn more about Markdown" %} </a>
+    </p>
+</div>
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/sidebar/recent_awards.html b/forum/modules/template_loader.py/forum/skins/default/templates/sidebar/recent_awards.html
new file mode 100644 (file)
index 0000000..b530677
--- /dev/null
@@ -0,0 +1,17 @@
+{% load i18n %}\r
+\r
+<div class="boxC">\r
+    <h3>{% trans "Recent awards" %}</h3>\r
+    <div class="body">\r
+         <ul class="badge-list">\r
+         {% for award in awards %}\r
+            <li>\r
+            <a href="{% url badges %}{{award.badge.id}}/{{award.badge.name|slugify}}" title="{{ award.badge.description }}" class="medal">\r
+            <span class="badge{{ award.badge.type }}">&#9679;</span>&nbsp;{{ award.badge.name }}</a>\r
+            <a href="{{ award.user.get_profile_url }}">{{ award.user.username }}</a>\r
+            </li>\r
+        {% endfor %}\r
+        </ul>\r
+        <div class="more"><a href="{% url badges %}">{% trans "all awards" %} </a> </div>\r
+     </div>\r
+</div>
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/sidebar/recent_tags.html b/forum/modules/template_loader.py/forum/skins/default/templates/sidebar/recent_tags.html
new file mode 100644 (file)
index 0000000..6ec6fc8
--- /dev/null
@@ -0,0 +1,13 @@
+{% load i18n %}\r
+\r
+<div class="boxC">\r
+       <h3>{% trans "Recent tags" %}</h3>\r
+       <div class="body">\r
+         <div class="tags" id="recent-tags">\r
+        {% for tag in tags %}\r
+            <a rel="tag" class="tag-link-{{ tag.name }}" title="{% blocktrans with tag.name as tagname %}see questions tagged '{{tagname}}'{% endblocktrans %}" href="{% url tag_questions tag.name|urlencode %}">{{ tag.name }}</a>\r
+        {% endfor %}\r
+        </div>\r
+        <div class="more"><a href="{% url tags %}">{% trans "popular tags" %} </a> </div>\r
+    </div>\r
+</div>
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/sidebar/user_blocks.html b/forum/modules/template_loader.py/forum/skins/default/templates/sidebar/user_blocks.html
new file mode 100644 (file)
index 0000000..d3d98cc
--- /dev/null
@@ -0,0 +1,9 @@
+{% load markup %}
+
+{% if show %}
+{% if wrap %}<div id="{{ blockid }}" class="boxC">
+    <div class="body">{% endif %}
+        {{ content }}
+     {% if wrap %}</div>
+</div>{% endif %}
+{% endif %}
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/static.html b/forum/modules/template_loader.py/forum/skins/default/templates/static.html
new file mode 100644 (file)
index 0000000..eff93ae
--- /dev/null
@@ -0,0 +1,12 @@
+{% extends "base_content.html" %}
+{% load i18n %}
+{% load markup %}
+{% block title %}{% spaceless %}{{ title }}{% endspaceless %}{% endblock %}
+
+{% block content %}
+<div class="headNormal">{{ title }}</div>
+<div class="content">
+{{ content|markdown:"settingsparser" }}
+</div>
+{% endblock %}
+
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/subscription_status.html b/forum/modules/template_loader.py/forum/skins/default/templates/subscription_status.html
new file mode 100644 (file)
index 0000000..d97dccd
--- /dev/null
@@ -0,0 +1,44 @@
+{% spaceless %}\r
+{% load i18n extra_tags %}\r
+<h3 class="subtitle">{% trans "Follow this question" %}</h3>\r
+<strong>{% trans "By Email" %}:</strong>\r
+{% if request.user.is_authenticated %}\r
+    <div class="subscription-status">\r
+        {% if subscription %}\r
+            {% if subscription.auto_subscription %}\r
+                <p>{% trans "You were automatically subscribed to this question." %}</p>\r
+            {% else %}\r
+                <p>{% trans "You are subscribed to this question." %}</p>\r
+            {% endif %}\r
+        {% else %}\r
+            <p>{% trans "You are not subscribed to this question." %}</p>\r
+        {% endif %}\r
+    </div>\r
+    <p><a class="ajax-command sidebar_button subscription_switch" href="{% url subscribe_simple id=question.id %}">\r
+        {% if subscription %}\r
+            {% trans "unsubscribe me" %}\r
+        {% else %}\r
+            {% trans "subscribe me" %}\r
+        {% endif %}\r
+    </a></p>\r
+    <p>\r
+        {% url user_subscriptions id=request.user.id,slug=request.user.username|slugify as subscriptions_url %}\r
+        {% blocktrans %}\r
+            (you can adjust your notification settings on your <a href="{{ subscriptions_url }}">profile</a>)\r
+        {% endblocktrans %}\r
+    </p>\r
+{% else %}\r
+    <p>{% trans "Once you sign in you will be able to subscribe for any updates here" %}</p>\r
+{% endif %}\r
+<strong>{% trans "By RSS" %}:</strong>\r
+<p>\r
+    <a class="feed-icon" style="background-image:url('{% media "media/images/feed-icon-small.png" %}');"\r
+        href="{{ question.get_absolute_url }}?type=rss" title="{% trans "subscribe to answers" %}"></a>\r
+    {% trans "Answers" %}\r
+</p>\r
+<p>\r
+    <a class="feed-icon" style="background-image:url('{% media "media/images/feed-icon-small.png" %}');"\r
+        href="{{ question.get_absolute_url }}?type=rss&comments=yes" title="{% trans "subscribe to comments and answers" %}"></a>\r
+    {% trans "Answers and Comments" %}\r
+</p>\r
+{% endspaceless %}\r
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/tag_selector.html b/forum/modules/template_loader.py/forum/skins/default/templates/tag_selector.html
new file mode 100644 (file)
index 0000000..91967b2
--- /dev/null
@@ -0,0 +1,42 @@
+{% load i18n %}
+{% load extra_tags %}
+<div id="tagSelector" class="boxC">
+       <h3 class="subtitle">{% trans "Interesting tags" %}</h3>
+    <div class="tags interesting marked-tags">
+    {% for tag_name in interesting_tag_names %}
+        {% spaceless %}
+        <span class="deletable-tag tag-link-{{ tag }}" id="interesting-tag-{{tag_name}}">
+            <a rel="tag" 
+                title="{% blocktrans with tag as tagname %}see questions tagged '{{ tag_name }}'{% endblocktrans %}"
+                href="{% url tag_questions tag_name|urlencode %}">{{tag_name}}</a>
+            <img class="delete-icon" 
+                src="{% media  "/media/images/close-small-dark.png" %}"
+                title="{% blocktrans %}remove '{{tag_name}}' from the list of interesting tags{% endblocktrans %}"/>
+        </span>
+        {% endspaceless %}
+    {% endfor %}
+    </div>
+    <input id="interestingTagInput" autocomplete="off" type="text"/>
+    <input id="interestingTagAdd" type="submit" value="{% trans "Add" %}"/>
+       <h3 class="subtitle">{% trans "Ignored tags" %}</h3>
+    <div class="tags ignored marked-tags">
+    {% for tag_name in ignored_tag_names %}
+        {% spaceless %}
+        <span class="deletable-tag tag-link-{{ tag }}" id="ignored-tag-{{tag_name}}">
+            <a rel="tag" 
+                title="{% blocktrans with tag as tagname %}see questions tagged '{{ tag_name }}'{% endblocktrans %}"
+                href="{% url tag_questions tag_name|urlencode %}">{{tag_name}}</a>
+            <img class="delete-icon" 
+                src="{% media  "/media/images/close-small-dark.png" %}"
+                title="{% blocktrans %}remove '{{tag_name}}' from the list of ignored tags{% endblocktrans %}"/>
+        </span>
+        {% endspaceless %}
+    {% endfor %}
+    </div>
+    <input id="ignoredTagInput" autocomplete="off" type="text"/>
+    <input id="ignoredTagAdd" type="submit" value="{% trans "Add" %}"/>
+    <p id="hideIgnoredTagsControl">
+    <input id="hideIgnoredTagsCb" type="checkbox" {% if request.user.hide_ignored_questions %}checked="checked"{% endif %} />
+    <label id="hideIgnoredTagsLabel" for="hideIgnoredTagsCb">{% trans "keep ignored questions hidden" %}</label>
+    <p>
+</div>
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/tags.html b/forum/modules/template_loader.py/forum/skins/default/templates/tags.html
new file mode 100644 (file)
index 0000000..56062c5
--- /dev/null
@@ -0,0 +1,63 @@
+{% extends "base_content.html" %}
+<!-- tags.html -->
+{% load i18n %}
+{% load extra_tags %}
+{% load humanize %}
+{% block title %}{% spaceless %}{% trans "Tag list" %}{% endspaceless %}{% endblock %}
+{% block forejs %}
+       <script type="text/javascript">
+       /*<![CDATA[*/
+        $().ready(function(){
+            $("#ipSearchTag").focus();
+
+            var orderby = "{{ tab_id }}";
+            if(orderby != "used" && orderby != "name")
+                orderby = "used";
+            $("#sort_" + orderby).attr('className',"on");
+            $("#type-tag").attr('checked',true);
+
+            Hilite.exact = false;
+            Hilite.elementid = "searchtags";
+            Hilite.debug_referrer = location.href;
+        });
+        /*]]>*/
+        </script>
+{% endblock %}
+{% block content %}
+<!-- Tabs -->
+<div class="tabBar">
+    <div class="headQuestions">{% trans "Tag list" %}</div>
+    {{ tags.paginator.sort_tabs }}
+</div>
+<div id="searchtags">
+<p>
+{% if stag %}
+    {% trans "All tags matching query" %} '<span class="darkred"><strong>{{ stag }}</strong></span>':
+{% endif %}
+{% if not tags.paginator.count %}
+    <span>{% trans "Nothing found" %}</span>
+{% endif %}
+</p>
+{% if tags.paginator.count %}
+<ul class="tagsList tags">
+{% for tag in tags.paginator.page %}
+   <li>
+    <a class="tag-link-{{ tag }}" href="{% url tag_questions tag|urlencode %}" title="{% trans "see questions tagged" %}'{{ tag }}'{% trans "using tags" %}" rel="tag">
+        {{ tag }}
+    </a>&nbsp;
+    <span class="tag-number">&#215; {{ tag.used_count|intcomma }}</span>
+    <br/>
+
+    </li>
+{% endfor %}
+</ul>
+{% endif %}
+</div>
+
+{% endblock %}
+{% block tail %}
+<div class="pager">
+    {{ tags.paginator.page_numbers }}
+</div>              
+{% endblock %}
+<!-- end tags.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/user.html b/forum/modules/template_loader.py/forum/skins/default/templates/user.html
new file mode 100644 (file)
index 0000000..ec852cc
--- /dev/null
@@ -0,0 +1,39 @@
+{% extends "base_content.html" %}
+<!-- user.html -->
+{% load extra_tags %}
+{% load extra_filters %}
+{% load humanize %}
+{% load smart_if %}
+
+{% block title %}{% spaceless %}{{ page_title }}{% endspaceless %}{% endblock %}
+{% block forestyle%}
+    <style type="text/css">
+               .history-table td { padding: 5px; }
+               .user-stats-table { margin-left:50px; }
+       </style>
+{% endblock %}
+{% block forejs %}
+    {% if request.user.is_superuser or request.user == view_user %}
+        <script type="text/javascript">google.load("jquery", "1.4.2");google.load("jqueryui", "1.8.1");</script>
+        <script type="text/javascript">
+            response_commands['update_profile_karma'] = function(new_karma) {
+                $('#user-reputation').css('background', 'yellow');
+                $('#user-reputation').html(new_karma);
+                $('#user-reputation').animate({ backgroundColor: "transparent" }, 1000);
+            }
+        </script>
+
+        <link rel="stylesheet" href="http://jquery-ui.googlecode.com/svn/tags/latest/themes/base/jquery-ui.css" type="text/css" media="all" />
+        <link rel="stylesheet" href="http://static.jquery.com/ui/css/demo-docs-theme/ui.theme.css" type="text/css" media="all" />
+        <link rel="stylesheet" type="text/css" media="screen" href="{% media "/media/style/user.css" %}"/>
+    {% endif %}
+    {% block userjs %}{% endblock %}
+{% endblock %}
+{% block content %}
+    <div id="mainbar-full">
+        {% include "users/info.html" %}
+        {% include "users/tabs.html" %}
+        {% block usercontent %}
+        {% endblock %}
+       </div>
+{% endblock %}<!-- end user.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/users/activity.html b/forum/modules/template_loader.py/forum/skins/default/templates/users/activity.html
new file mode 100644 (file)
index 0000000..0b6a914
--- /dev/null
@@ -0,0 +1,12 @@
+{% load extra_tags %}\r
+{% load humanize %}\r
+{% load extra_tags %}\r
+\r
+<div class="action_container">\r
+    <div class="action_body">\r
+        {{ describe }}\r
+    </div>\r
+    <div class="action_date" style="text-align: right;">\r
+        {% diff_date action.action_date  %}\r
+    </div>\r
+</div>
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/users/edit.html b/forum/modules/template_loader.py/forum/skins/default/templates/users/edit.html
new file mode 100644 (file)
index 0000000..3240fd2
--- /dev/null
@@ -0,0 +1,107 @@
+{% extends "base_content.html" %}\r
+<!-- user_edit.html -->\r
+{% load extra_tags %}\r
+{% load humanize %}\r
+{% load i18n %}\r
+{% block title %}{% spaceless %}{% trans "Edit user profile" %}{% endspaceless %}{% endblock %}\r
+{% block forejs %}\r
+        <script type="text/javascript">google.load("jquery", "1.4.2");google.load("jqueryui", "1.8.1");</script>\r
+\r
+        <link rel="stylesheet" href="http://jquery-ui.googlecode.com/svn/tags/latest/themes/base/jquery-ui.css" type="text/css" media="all" />\r
+        <link rel="stylesheet" href="http://static.jquery.com/ui/css/demo-docs-theme/ui.theme.css" type="text/css" media="all" />\r
+\r
+        <script type="text/javascript">\r
+            $().ready(function(){\r
+                $("#id_birthday").datepicker({\r
+                    changeMonth: true,\r
+                    changeYear: true,\r
+                    dateFormat: 'yy-mm-dd',\r
+                    minDate: null,\r
+                    maxDate: '0M 0D',\r
+                    yearRange: '1920:2010'\r
+                });\r
+\r
+                $("#nav_profile").attr('className',"on");\r
+                $("#cancel").bind('click', function(){history.go(-1);})\r
+            });     \r
+        </script>\r
+        {% block userjs %}\r
+        {% endblock %}\r
+{% endblock %}\r
+{% block content %}\r
+<div id="main-bar" class="headNormal">\r
+    {{ user.username }} - {% trans "edit profile" %}\r
+</div>\r
+<div id="main-body" style="width:100%;padding-top:10px">\r
+    <form name="" action="{% url edit_user user.id %}" method="post">\r
+        <div id="left" style="float:left;width:180px">\r
+            {% if user.email %}\r
+            {% gravatar user 128 %}\r
+            {% else %}\r
+            <img src="{% media  "/media/images/nophoto.png" %}">\r
+            {% endif %}\r
+            <div style="padding:20px 0 0 20px;font-weight:bold;font-size:150%">\r
+                <a href="http://www.gravatar.com/" target="_blank" \r
+                                       title="gravatar {% trans "image associated with your email address" %}">{% trans "gravatar" %}</a>\r
+            </div>\r
+        </div>\r
+        \r
+        <div id="askform" style="float:right;width:750px;text-align:left;">\r
+            <h2>{% trans "Registered user" %}</h2>\r
+            <table class="user-details">\r
+                <tr>\r
+                    <th width="100px"></th>\r
+                    <th></th>\r
+                </tr>\r
+                <tr style="height:35px">\r
+                       <td>{% trans "Screen Name" %}:</td>\r
+                       <td>\r
+                       {% if form.username %}\r
+                           {{ form.username }} <span class="form-error"></span> {{ form.username.errors }}\r
+                       {% else %}\r
+                           {{ user.username }}\r
+                       {% endif %}\r
+                       </td>\r
+                   </tr>\r
+                \r
+                   <tr style="height:35px">\r
+                       <td>{{ form.email.label_tag }}:</td>\r
+                       <td>{{ form.email }} <span class="form-error"></span> {{ form.email.errors }} </td>\r
+                   </tr>\r
+                <tr style="height:35px">\r
+                       <td></td>\r
+                       <td class="title-desc">{{ form.email.help_text }}</td>\r
+                   </tr>\r
+                <tr style="height:35px">\r
+                       <td>{{ form.realname.label_tag }}:</td>\r
+                       <td>{{ form.realname }} <span class="form-error"></span> {{ form.realname.errors }} </td>\r
+                   </tr>\r
+                <tr style="height:35px">\r
+                       <td>{{ form.website.label_tag }}:</td>\r
+                       <td>{{ form.website }} <span class="form-error"></span> {{ form.website.errors }} </td>\r
+                   </tr>\r
+                <tr style="height:35px">\r
+                       <td>{{ form.city.label_tag }}:</td>\r
+                       <td>{{ form.city }} <span class="form-error"></span> {{ form.city.errors }} </td>\r
+                   </tr>\r
+                <tr style="height:35px">\r
+                       <td>{{ form.birthday.label_tag }}:</td>\r
+                       <td>{{ form.birthday }} <span class="form-error"></span> {{ form.birthday.errors }} </td>\r
+                   </tr>\r
+                <tr>\r
+                       <td style="vertical-align:top">{{ form.about.label_tag }}:</td>\r
+                       <td>{{ form.about }} <span class="form-error"></span> {{ form.about.errors }} </td>\r
+                   </tr>\r
+                   \r
+            </table>\r
+            <div style="margin:30px 0 60px 0">\r
+                <input type="submit" value="{% trans "Update" %}" class="submit" >\r
+                <input id="cancel" type="button" value="{% trans "Cancel" %}" class="submit" >\r
+          \r
+            </div>\r
+        </div>\r
+    </form>\r
+    \r
+</div>\r
+{% endblock %}\r
+<!-- end user_edit.html -->\r
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/users/info.html b/forum/modules/template_loader.py/forum/skins/default/templates/users/info.html
new file mode 100644 (file)
index 0000000..efc49fd
--- /dev/null
@@ -0,0 +1,111 @@
+<!-- user_info.html -->
+{% load extra_tags %}
+{% load extra_filters %}
+{% load humanize %}
+{% load smart_if %}
+{% load i18n %}
+{% load markup %}
+{% load user_tags %}
+
+<div id="subheader" class="headUser{% if view_user.is_suspended %} suspended-user{% endif %}">
+    {{view_user.decorated_name}}
+</div>
+<table class="user-info-table">
+    <tr>
+        <td width="180" style="vertical-align:middle;text-align:center;">
+            <table width="100%">
+                <tr>
+                    <td>
+                        {% gravatar view_user 128 %}
+                    </td>
+                </tr>
+                <tr>
+                    <td align="center">
+                        {% if not view_user.is_suspended %}
+                            <div class="scoreNumber" id="user-reputation">{{view_user.reputation|intcomma}}</div>
+                            <p><b style="color:#777;">{% trans "reputation" %}</b></p>
+                        {% else %}
+                            <div class="scoreNumber">{% trans "Suspended" %}</div>
+                            <p>{{ view_user.suspension.extra.publicmsg }}</p>
+                        {% endif %}
+                    </td>
+                </tr>
+            </table>
+        </td>
+        <td width="360" style="vertical-align: top;">
+        {% if can_view_private %}{% user_menu request.user view_user %}{% endif %}
+            <table class="user-details">
+                <tr>
+                    <th colspan="2" align="left"><h3>{% trans "Registered user" %}</h3></th>
+                </tr>
+                {% if view_user.real_name %}
+                <tr>
+                    <td>{% trans "real name" %}</td>
+                    <td><b>{{view_user.real_name}}</b></td>
+                </tr>
+                {% endif %}
+                <tr>
+                    <td>{% trans "member for" %}</td>
+                    <td><strong>{% diff_date view_user.date_joined %}</strong></td>
+                </tr>
+                {% if view_user.last_seen %}
+                <tr>
+                    <td>{% trans "last seen" %}</td>
+                    <td><strong title="{{ view_user.last_activity }}">{% diff_date view_user.last_activity %}</strong></td>
+                </tr>
+                {% endif %}
+                {% if view_user.website %}
+                <tr>
+                    <td>{% trans "user's website" %}</td>
+                    <td><a rel="nofollow" target="_blank" href="{{view_user.website}}">{{view_user.website}}</a></td>
+                </tr>
+                {% endif  %}
+                {% if view_user.location %}
+                <tr>
+                    <td>{% trans "location" %}</td>
+                    <td>{{view_user.location}}</td>
+                </tr>
+                {% endif %}
+                {% if view_user.date_of_birth%}
+                <tr>
+                                       <!--todo  - redo this with blocktrans -->
+                    {% if view_user.date_of_birth.year != 1900%}
+                    <td>{% trans "age" %}</td>
+                    <td>{% get_age view_user.date_of_birth %} {% trans "age unit" %}</td>
+                    {% endif %}
+                </tr>
+                {% endif %}
+                {% if can_view_private %}
+                <tr>
+                    <td>{% trans "email" %}</td>
+                    <td>
+                        <a href="mailto: {{ view_user.email }}">{{ view_user.email }}</a>
+                        {% if not view_user.email_isvalid %}
+                            ({% trans "not validated" %})
+                            {% ifequal request.user view_user %}
+                                </td></tr><tr><td></td><td><a href="{% url send_validation_email %}">{% trans "Send me a validation link." %}</a>
+                            {% endifequal %}
+                        {% endif %}
+                    </td>
+                </tr>
+                {% endif %}
+                               <!--
+                {% if votes_today_left %}
+                <tr>
+                    <td>{% trans "todays unused votes" %}</td>
+                    <td><strong class="darkred">{{ votes_today_left }}</strong> {% trans "votes left" %}</td>
+                </tr>
+                {% endif %}
+                               -->
+            </table>
+        </td>
+        <td width="380">
+            <div class="user-about">
+            {% if view_user.about %}
+                {{view_user.about|markdown}}
+            {% endif %}
+            </div>
+        </td>
+    </tr>
+</table>
+<!-- end user_info.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/users/karma_bonus.html b/forum/modules/template_loader.py/forum/skins/default/templates/users/karma_bonus.html
new file mode 100644 (file)
index 0000000..b39c276
--- /dev/null
@@ -0,0 +1,12 @@
+{% load i18n %}
+
+<table>
+    <tr>
+        <th>{% trans "Points" %}:</th>
+        <td><input type="text" id="points-to-award" name="points" value="1" /></td>
+    </tr>
+    <tr>
+        <th>{% trans "Message" %}:</th>
+        <td><textarea id="award-message" name="message"></textarea></td>
+    </tr>
+</table>
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/users/menu.html b/forum/modules/template_loader.py/forum/skins/default/templates/users/menu.html
new file mode 100644 (file)
index 0000000..24d213d
--- /dev/null
@@ -0,0 +1,8 @@
+{% load i18n smart_if ui_registry %}\r
+\r
+<div id="user-menu-container" class="context-menu">\r
+    <span id="user-menu" class="context-menu-trigger">{% trans "User tools" %} &#9660;</span>\r
+    <ul id="user-menu-dropdown" class="context-menu-dropdown">\r
+        {% loadregistry user_menu %}{% endloadregistry %}\r
+    </ul>\r
+</div>\r
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/users/online_users.html b/forum/modules/template_loader.py/forum/skins/default/templates/users/online_users.html
new file mode 100644 (file)
index 0000000..903e895
--- /dev/null
@@ -0,0 +1,54 @@
+{% extends "base_content.html" %}
+<!-- users.html -->
+{% load extra_tags %}
+{% load humanize %}
+{% load i18n %}
+{% block title %}{% spaceless %}{% trans "Users Online" %}{% endspaceless %}{% endblock %}
+{% block forejs %}
+        <script type="text/javascript">
+           //todo move javascript out
+        $().ready(function(){
+            $("#type-user").attr('checked',true);
+            var orderby = "{{ tab_id }}";
+            $("#sort_" + orderby).attr('className',"on");
+
+            Hilite.exact = false;
+            Hilite.elementid = "main-body";
+            Hilite.debug_referrer = location.href;
+        });
+        </script>
+{% endblock %}
+{% block content %}
+<div class="tabBar">
+    <div class="headUsers">{% trans "Users Online" %}</div>
+    {{ users.paginator.sort_tabs }}
+</div>
+<div id="main-body" style="width:100%">
+    <p>
+        {% if suser %}
+                       {% blocktrans %}users matching query {{suser}}:{% endblocktrans %}
+        {% endif %}
+
+        {% if not users.paginator.count %}
+            <span>{% trans "Nothing found." %}</span>
+        {% endif %}
+    </p>
+    <div class="userList">
+        {% for user in users.paginator.page %}
+        <div class="user">
+            <ul>
+                <li class="thumb"><a href="{{ user.get_profile_url }} ">{% gravatar user 32 %}</a></li>
+                <li><a {% if user.is_suspended %}class="suspended-user" {% endif %}href="{{ user.get_profile_url }}">{{ user.decorated_name }}</a></li>
+                <li>{% get_score_badge user %}</li>
+            </ul>
+        </div>
+        {% endfor %}
+    </div>
+</div>
+{% endblock %}
+{% block tail %}
+<div class="pager">
+    {{ users.paginator.page_numbers }}
+</div>
+{% endblock %}
+<!-- end users.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/users/preferences.html b/forum/modules/template_loader.py/forum/skins/default/templates/users/preferences.html
new file mode 100644 (file)
index 0000000..f9393ac
--- /dev/null
@@ -0,0 +1,29 @@
+{% extends "user.html" %}
+{% load i18n %}
+{% load extra_tags %}
+
+{% block usercontent %}
+    <h2>{% trans "Preferences" %}</h2>
+    <div class='inline-block'>
+    <form method="POST">
+        <p class="message">
+            {% trans "Here you can set some personal preferences." %}
+        </p>
+        {{ form.errors }}
+        <table class="form-as-table">
+            <tr>
+                <td colspan="2">
+                    <strong>{% trans "Navigation:" %}</strong>
+                </td>
+            </tr>
+            <tr>
+                <td>{{ form.sticky_sorts }}</td>
+                <td>{% trans "Allways remember the sort order I apply to the lists I view" %}</td>
+            </tr>
+        </table>
+        <div class="submit-row">
+            <input type="submit" class="submit" name="save" value="{% trans "Save" %}"/>
+        </div>
+    </form>
+    </div>
+{% endblock %}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/users/questions.html b/forum/modules/template_loader.py/forum/skins/default/templates/users/questions.html
new file mode 100644 (file)
index 0000000..21c193c
--- /dev/null
@@ -0,0 +1,11 @@
+{% extends "user.html" %}
+
+{% load extra_tags %}
+{% load question_list_tags %}
+{% block usercontent %}
+<div class="user-stats-table">
+    {% for favorite in favorites %}
+        {% question_list_item favorite.node favorite_count=yes signature_type=badges %}
+    {% endfor %}
+</div>
+{% endblock %}
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/users/recent.html b/forum/modules/template_loader.py/forum/skins/default/templates/users/recent.html
new file mode 100644 (file)
index 0000000..5098df6
--- /dev/null
@@ -0,0 +1,12 @@
+{% extends "user.html" %}
+
+{% load extra_tags %}
+{% load user_tags %}
+{% block usercontent %}
+        <div style="padding-top:5px;font-size:13px;">
+        {% for act in activities %}
+            {% activity_item act request.user %} 
+        {% endfor %}
+        </div>
+{% endblock %}
+
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/users/reputation.html b/forum/modules/template_loader.py/forum/skins/default/templates/users/reputation.html
new file mode 100644 (file)
index 0000000..5b1559c
--- /dev/null
@@ -0,0 +1,43 @@
+{% extends "user.html" %}
+<!-- user_reputation.html -->
+{% load extra_tags %}
+{% load extra_filters %}
+{% load humanize %}
+{% load user_tags %}
+{% block userjs %}
+       <script type='text/javascript' src='{% media  "/media/js/excanvas.min.js" %}'></script>
+       <script type='text/javascript' src='{% media  "/media/js/jquery.flot.min.js" %}'></script>
+       
+       <script type="text/javascript">
+        $().ready(function(){
+            var d = {{ graph_data }};
+            var placeholder = $("#diagram");
+
+            var plot = $.plot(placeholder, [d], {
+                xaxis: { mode: "time" },
+                points: { show: true },
+                lines: { show: true }
+            });
+        });
+
+        </script>
+{% endblock %}
+{% block usercontent %}
+        <div style="padding:5px;font-size:13px;">
+            <div id="diagram" style="width:550px;height:250px;float:left">
+
+            </div>
+            <div style="float:right; width:385px; height:300px; overflow-y:auto;word-wrap:break-word;" >
+                {% for rep in reputation %}
+                <p style="clear:both">
+                    <div style="float:left;text-align:right;font-family:arial;font-weight:bold;background:#eee;padding:2px 10px 2px 10px;margin-right:5px">
+                        <div style="float:left;width:20px;color:green;padding-right:5px">{{ rep.positive }}</div>
+                        <div style="float:left;width:20px;color:red">{{ rep.negative }}</div>
+                        
+                    </div>
+                    {% activity_item rep.action request.user %}<br/>
+                </p>
+                {% endfor %}
+            </div>
+        </div>
+{% endblock %}<!-- end user_reputation.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/users/signature.html b/forum/modules/template_loader.py/forum/skins/default/templates/users/signature.html
new file mode 100644 (file)
index 0000000..e8aebf3
--- /dev/null
@@ -0,0 +1,33 @@
+{% load i18n extra_filters %}{% spaceless %}\r
+\r
+{% if not user.is_suspended %}\r
+    {% ifequal format "full" %}\r
+\r
+    {% else %}\r
+        <a href="{{ user.get_absolute_url }}">{{ user.decorated_name }}</a>\r
+        <span class="score" title="{{ user.reputation }} {% trans "reputation" %}">{{ user.reputation|decorated_int:"" }}</span>\r
+        {% ifequal format "badges" %}\r
+            {% if user.gold %}\r
+            <span title="{{ user.gold }} {% trans "badges" %}">\r
+                <span class="badge1">&#9679;</span>\r
+                <span class="badgecount">{{ user.gold }}</span>\r
+            </span>\r
+            {% endif %}\r
+            {% if user.silver %}\r
+            <span title="{{ user.silver }} {% trans "badges" %}">\r
+                <span class="silver">&#9679;</span>\r
+                <span class="badgecount">{{ user.silver }}</span>\r
+            </span>\r
+            {% endif %}\r
+            {% if user.bronze %}\r
+            <span title="{{ user.bronze }} {% trans "badges" %}">\r
+                <span class="bronze">&#9679;</span>\r
+                <span class="badgecount">{{ user.bronze }}</span>\r
+            </span>\r
+            {% endif %}\r
+        {% endifequal %}\r
+    {% endifequal %}\r
+{% else %}\r
+    <a class="suspended-user" href="{{ user.get_absolute_url }}">{{ user.decorated_name }}</a>{% trans "(suspended)" %}\r
+{% endif %}\r
+{% endspaceless %}\r
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/users/stats.html b/forum/modules/template_loader.py/forum/skins/default/templates/users/stats.html
new file mode 100644 (file)
index 0000000..8fb67f9
--- /dev/null
@@ -0,0 +1,145 @@
+{% extends "user.html" %}
+<!-- user_stats.html -->
+{% load i18n %}
+{% load extra_tags %}
+{% load extra_filters %}
+{% load humanize %}
+{% load question_list_tags %}
+               {% block usercontent %}
+
+        <a name="questions"></a>
+        {% spaceless %}
+            <h2>
+                {% blocktrans count questions.paginator.count as counter %}
+                <span class="count">{{counter}}</span> Question
+                {% plural %}
+                <span class="count">{{counter}}</span> Questions
+                {% endblocktrans %}
+                <a class="feed-icon" style="background-image:url('{% media "media/images/feed-icon-small.png" %}');"
+                    href="{{ view_user.get_asked_url }}?type=rss" title="{% trans "subscribe to question RSS feed" %}"></a>
+            </h2>
+        {% endspaceless %}
+        <div>{{ questions.paginator.sort_tabs }}</div>
+               <div id="listA" class="user-stats-table">
+                   {% for question in questions.paginator.page %}
+                       {% question_list_item question favorite_count=yes signature_type=badges %}
+                   {% endfor %}
+               </div>
+               <br clear="all"/>
+               <div class="pager">{{ questions.paginator.page_numbers }}</div>
+               <br clear="all"/>
+
+        <a name="answers"></a>
+        {% spaceless %}
+            <h2>
+                {% blocktrans count answers.paginator.count as counter %}
+                <span class="count">{{counter}}</span> Answer
+                {% plural %}
+                <span class="count">{{counter}}</span> Answers
+                {% endblocktrans %}
+            </h2>
+        {% endspaceless %}
+        <div>{{ answers.paginator.sort_tabs }}</div>
+        <div class="user-stats-table">
+            {% for answer in answers.paginator.page %}
+            <div class="answer-summary">
+                <a title="{{answer.question.title}}"
+                    href="{{ answer.get_absolute_url }}">
+                    <span class="{% if answer.nis.accepted %}answered-accepted {% endif %} answer-votes" 
+                                               title="{% blocktrans with answer.score as vote_count %}the answer has been voted for {{ vote_count }} times{% endblocktrans %} {% if answer.nis.accepted %}{% trans "this answer has been selected as correct" %}{%endif%}">
+                        {{ answer.score }}
+                    </span>
+                </a>
+                <div class="answer-link">
+                    {% spaceless %}
+                    <a href="{{ answer.get_absolute_url }}">{{answer.headline}}</a>
+                    {% endspaceless %}
+                </div>
+            </div>
+            {% endfor %}
+        </div>
+        <br clear="all"/>
+               <div class="pager">{{ answers.paginator.page_numbers }}</div>
+        <br clear="all"/>
+        <a name="votes"></a>
+        {% spaceless %}
+            <h2>
+                {% blocktrans count total_votes as cnt %}
+                    <span class="count">{{cnt}}</span> Vote
+                {% plural %}
+                    <span class="count">{{cnt}}</span> Votes
+                {% endblocktrans %}
+            </h2>
+        {% endspaceless %}
+        <div class="user-stats-table">
+            <table>
+                <tr>
+                    <td width="60">
+                        <img style="cursor: default;" src="{% media  "/media/images/vote-arrow-up-on.png" %}" alt="{% trans "thumb up" %}" />
+                            <span title="{% trans "user has voted up this many times" %}" class="vote-count">{{up_votes}}</span>
+
+                    </td>
+                    <td width="60">
+                        <img style="cursor: default;" src="{% media  "/media/images/vote-arrow-down-on.png" %}" alt="{% trans "thumb down" %}" />
+                            <span title="{% trans "user voted down this many times" %}" class="vote-count">{{down_votes}}</span>
+
+                    </td>
+                </tr>
+            </table>
+        </div>
+        <a name="tags"></a>
+        {% spaceless %}
+            <h2>
+                {% blocktrans count user_tags|length as counter %}
+                    <span class="count">{{counter}}</span> Tag
+                {% plural %}
+                    <span class="count">{{counter}}</span> Tags
+                {% endblocktrans %}
+            </h2>
+        {% endspaceless %}
+        <div class="user-stats-table">
+            <table class="tags">
+                <tr style="vertical-align: top;">
+                    <td valign="top" style="padding-right: 20px;">
+                        {% for tag in user_tags%}
+                        <a rel="tag" 
+                            class="tag-link-{{ tag.name }}"
+                                                       title="{% blocktrans with tag.name as tag_name %}see other questions with {{view_user}}'s contributions tagged '{{ tag_name }}' {% endblocktrans %}"
+                                                       href="{% url tag_questions tag|urlencode %}?user={{view_user.username}}">{{tag.name}}</a>
+                        <span class="tag-number">&#215; {{ tag.user_tag_usage_count|intcomma }}</span><br/>
+                            {% if forloop.counter|divisibleby:"10" %}
+                                </td>
+                                <td width="180"  valign="top">
+                            {% endif %}
+                        {% endfor %}
+                    </td>
+                </tr>
+            </table>
+        </div>
+        <a name="badges"></a>
+        {% spaceless %}
+        <h2>
+            {% blocktrans count total_awards as counter %}
+            <span class="count">{{counter}}</span> Badge
+            {% plural %}
+            <span class="count">{{counter}}</span> Badges
+            {% endblocktrans %}
+        </h2>
+        {% endspaceless %}
+        <div class="user-stats-table">
+            <table>
+                <tr style="vertical-align: top;">
+                    <td style="line-height:35px; padding-right: 20px;">
+                        {% for award, count in awards %}
+                            <a href="{% url badges %}{{award.id}}/{{award.name|slugify}}" title="{{ award.description }}" class="medal"><span class="badge{{ award.type }}">&#9679;</span>&nbsp;{{ award.name }}</a><span class="tag-number"> &#215; {{ count|intcomma }}</span><br/>
+                            {% if forloop.counter|divisibleby:"6" %}
+                                </td>
+                                <td width="180" style="line-height:35px">
+                            {% endif %}
+                        {% endfor %}
+                    </td>
+                </tr>
+            </table>
+        </div>
+{% endblock %}
+<!-- end user_stats.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/users/subscriptions.html b/forum/modules/template_loader.py/forum/skins/default/templates/users/subscriptions.html
new file mode 100644 (file)
index 0000000..573bb0a
--- /dev/null
@@ -0,0 +1,53 @@
+{% extends "user.html" %}
+<!-- user_subscriptions.html -->
+{% load i18n %}
+{% load extra_tags %}
+{% load humanize %}
+
+{% block userjs %}
+    <script type="text/javascript">
+        function enableSettings() {
+            $("div#subscriptions_settings").show();
+            $("div#subscriptions_management").hide();
+
+            $("a#subscriptions_settings_button").addClass('on');
+            $("a#subscriptions_management_button").removeClass("on");
+
+            //location.reload(true);
+        }
+
+        function enableManagement() {
+            $("div#subscriptions_settings").hide();
+            $("div#subscriptions_management").show();
+
+            $("a#subscriptions_settings_button").removeClass('on');
+            $("a#subscriptions_management_button").addClass('on');
+
+            //location.reload(true);
+        }
+    </script>
+{% endblock %}
+
+{% block usercontent %}
+    <br/>
+
+    <div id="navBar"><div class="tabsA">
+        <a href='{% url user_subscriptions id=view_user.id slug=view_user.username|slugify %}?tab=settings' id="subscriptions_settings_button"  {%  if not manage_open %}class="on"{% endif %}>Settings</a>
+        <a href='{% url user_subscriptions id=view_user.id slug=view_user.username|slugify %}?tab=manage' id="subscriptions_management_button"  {%  if manage_open %}class="on"{% endif %}>Manage</a>
+    </div></div>
+
+    <br/>
+
+    {% if not manage_open %}
+        <div id="subscriptions_settings" >
+            {% include "users/subscriptions_settings.html" %}
+        </div>
+    {% endif %}
+
+    {% if manage_open %}
+        <div id="subscriptions_management" >
+            {% include "users/subscriptions_management.html" %}
+        </div>
+    {% endif %}
+{% endblock %}
+<!-- end user_subscriptions.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/users/subscriptions_management.html b/forum/modules/template_loader.py/forum/skins/default/templates/users/subscriptions_management.html
new file mode 100644 (file)
index 0000000..a0d921e
--- /dev/null
@@ -0,0 +1,26 @@
+{% load i18n %}
+{% load question_list_tags %}
+
+<div id="subscription_list" align="left">
+    <h2>
+        {% trans "Manage your current subscriptions" %}
+        <span style="font-size:11px">
+            {% if auto %}
+                <a href='{% url user_subscriptions id=view_user.id slug=view_user.username|slugify %}?auto=False&tab=manage'>{% trans "don't show auto-subscribe" %}</a>
+            {% else %}
+                <a href='{% url user_subscriptions id=view_user.id slug=view_user.username|slugify %}?auto=True&tab=manage'>{% trans "show auto-subscribe" %}</a>
+            {% endif %}
+        </span>
+    </h2>
+
+    {% for subscription in subscriptions.paginator.page %}
+        {% subscription_list_item subscription subscription.question %}
+    {% endfor %}
+
+    <div class="pager">{{ subscriptions.paginator.page_numbers }}</div>
+</div>
+
+<br />
+<br />
+
+<!-- end user_subscriptions.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/users/subscriptions_settings.html b/forum/modules/template_loader.py/forum/skins/default/templates/users/subscriptions_settings.html
new file mode 100644 (file)
index 0000000..9c88602
--- /dev/null
@@ -0,0 +1,127 @@
+{% load i18n %}\r
+{% load extra_tags %}\r
+{% load humanize %}\r
+\r
+<h2>{% trans "Notifications and subscription settings" %}</h2>\r
+<p class="message">\r
+    {% blocktrans %}\r
+    Here you can decide which types of notifications you wish to receive, and their frequency.<br />\r
+    {% endblocktrans %}\r
+    {% if notificatons_on %}\r
+    {% blocktrans %}\r
+    Currently you have notifications enabled. You can always stop all notifications without losing your settings and restart them afterwards.<br />\r
+    {% endblocktrans %}\r
+    {% else %}\r
+    {% blocktrans %}\r
+    Currently you have notifications disabled. You can enable them by clicking on the <strong>Start notifications</strong> button below.<br />\r
+    {% endblocktrans %}\r
+    {% endif %}\r
+</p>\r
+<div class='inline-block'>\r
+<form method="POST">\r
+    {{ form.errors }}\r
+    <table class="form-as-table">\r
+        <tr>\r
+            <td colspan="2">\r
+                <strong>{% trans "Notify me when:" %}</strong>\r
+            </td>\r
+        </tr>\r
+        <tr>\r
+            <td>{% trans "A new member joins" %}</td>\r
+            <td>{{ form.member_joins }}</td>\r
+        </tr>\r
+        <tr>\r
+            <td>{% trans "A new question is posted" %}</td>\r
+            <td>{{ form.new_question }}</td>\r
+        </tr>\r
+        <tr>\r
+            <td>{% trans "A new question matching my interesting tags is posted" %}</td>\r
+            <td>{{ form.new_question_watched_tags }}</td>\r
+        </tr>\r
+        <tr>\r
+            <td>{% trans "There's an update on one of my subscriptions" %}</td>\r
+            <td >{{ form.subscribed_questions }}</td>\r
+        </tr>\r
+    </table>\r
+    <p>&nbsp;</p>\r
+    <table class="form-as-table check-table">\r
+        <tr>\r
+            <td colspan="3">\r
+                <strong>{% trans "Auto subscribe me to:" %}</strong>\r
+            </td>\r
+        </tr>\r
+        <tr>\r
+            <td>\r
+                {{ form.questions_asked }}{% trans "Questions I ask" %}\r
+            </td>\r
+            <td>\r
+                {{ form.questions_answered }}{% trans "Questions I answer" %}\r
+            </td>\r
+            <td>\r
+                {{ form.questions_commented }}{% trans "Questions I comment" %}\r
+            </td>\r
+        </tr>\r
+        <tr>\r
+            <td>\r
+                {{ form.questions_viewed }}{% trans "Questions I view" %}\r
+            </td>\r
+            <td>\r
+                {{ form.all_questions_watched_tags }}{% trans "All questions matching my interesting tags" %}\r
+            </td>\r
+            <td>\r
+                {{ form.all_questions }}{% trans "All questions" %}\r
+            </td>\r
+        </tr>\r
+    </table>\r
+    <p>&nbsp;</p>\r
+    <table class="form-as-table check-table">\r
+        <tr>\r
+            <td colspan="2">\r
+                <strong>{% trans "On my subscriptions, notify me when:" %}</strong>\r
+            </td>\r
+        </tr>\r
+        <tr>\r
+            <td>\r
+                {{ form.notify_answers }}{% trans "An answer is posted" %}\r
+            </td>\r
+            <td>\r
+                {{ form.notify_comments_own_post }}{% trans "A comment on one of my posts is posted" %}\r
+            </td>\r
+        </tr>\r
+        <tr>\r
+            <td>\r
+                {{ form.notify_comments }}{% trans "A comment is posted" %}\r
+            </td>\r
+            <td>\r
+                {{ form.notify_accepted }}{% trans "An answer is accepted" %}\r
+            </td>\r
+        </tr>\r
+    </table>\r
+    <p>&nbsp;</p>\r
+    <table class="form-as-table check-table">\r
+        <tr>\r
+            <td>\r
+                <strong>{% trans "More:" %}</strong>\r
+            </td>\r
+        </tr>\r
+        <tr>\r
+            <td>\r
+                {{ form.notify_reply_to_comments }}{% trans "Notify me when someone replies to one of my comments on any post using the <pre>@username</pre> notation" %}\r
+            </td>\r
+        </tr>\r
+        <tr>\r
+            <td>\r
+                {{ form.send_digest }}{% trans "Send me the daily digest with information about the site activity" %}\r
+            </td>\r
+        </tr>\r
+    </table>\r
+    <div class="submit-row">\r
+        <input type="submit" class="submit" name="save" value="{% trans "Update" %}"/>\r
+        {% if notificatons_on %}\r
+        <input type="submit" class="submit" name="notswitch" value="{% trans "Stop notifications" %}"/>\r
+        {% else %}\r
+        <input type="submit" class="submit" name="notswitch" value="{% trans "Start notifications" %}"/>\r
+        {% endif %}\r
+    </div>\r
+</form>\r
+</div>\r
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/users/suspend_user.html b/forum/modules/template_loader.py/forum/skins/default/templates/users/suspend_user.html
new file mode 100644 (file)
index 0000000..e131418
--- /dev/null
@@ -0,0 +1,49 @@
+{% load i18n %}
+
+<table>
+    <caption><h2>{% trans "Suspend user" %}</h2></caption>
+    <tr>
+        <td>
+            <select name="bantype" id="bantype">
+                <option value="indefinitely">{% trans "Indefinetly" %}</option>
+                <option value="forxdays">{% trans "For X days" %}</option>
+            </select>
+        </td>
+    </tr>
+    <tr id="forxdays" style="display: none">
+        <td>
+            {% trans "Suspend for" %}<input type="text" size="3" style="width: 30px; height: 1.2em; margin: 0 0.5em 0 0.5em; font-size: 1em;" name="forxdays" value="3" />{% trans "days" %}
+        </td>
+    </tr>
+    <tr>
+        <td>
+            <p><b>{% trans "Public message" %}:</b></p>
+        </td>
+    </tr>
+    <tr>
+        <td>
+            <textarea rows="3" name="publicmsg" cols="35"></textarea><br />
+            <small>{% trans "This message will be visible through the user activity log."  %}</small>
+        </td>
+    </tr>
+    <tr>
+        <td>
+            <p><b>{% trans "Private message" %}:</b></p>
+        </td>
+    </tr>
+    <tr>
+        <td>
+            <textarea rows="3" name="privatemsg" cols="35"></textarea><br />
+            <small>{% trans "If set, only the suspended user will see this message."  %}</small>
+        </td>
+    </tr>
+</table>
+<script type="text/javascript">
+    $('#bantype').change(function() {
+        if ($(this).val() == 'forxdays') {
+            $('#forxdays').slideDown('fast');
+        } else {
+            $('#forxdays').slideUp('fast');
+        }
+    });
+</script>
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/users/tabs.html b/forum/modules/template_loader.py/forum/skins/default/templates/users/tabs.html
new file mode 100644 (file)
index 0000000..d3d8d90
--- /dev/null
@@ -0,0 +1,12 @@
+{% load extra_filters ui_registry i18n %}
+{% with view_user.username|slugify as user_slug %}
+<div class="tabBar">
+    <div class="tabsA">
+        {% loopregistry profile_tabs %}{% spaceless %}
+            <a title="{{ tab_description }}" id="{{ tab_name }}" {% ifequal active_tab tab_name %}class="on"{% endifequal %} href="{{ tab_url }}">
+                {{ tab_title }}
+            </a>
+        {% endspaceless %}{% endloopregistry %}
+    </div>
+</div>
+{% endwith %}
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/users/users.html b/forum/modules/template_loader.py/forum/skins/default/templates/users/users.html
new file mode 100644 (file)
index 0000000..d7e01db
--- /dev/null
@@ -0,0 +1,54 @@
+{% extends "base_content.html" %}
+<!-- users.html -->
+{% load extra_tags %}
+{% load humanize %}
+{% load i18n %}
+{% block title %}{% spaceless %}{% trans "Users" %}{% endspaceless %}{% endblock %}
+{% block forejs %}
+       <script type="text/javascript">
+          //todo move javascript out
+        $().ready(function(){
+            $("#type-user").attr('checked',true);
+            var orderby = "{{ tab_id }}";
+            $("#sort_" + orderby).attr('className',"on");
+            
+            Hilite.exact = false;
+            Hilite.elementid = "main-body";
+            Hilite.debug_referrer = location.href;
+        });
+        </script>
+{% endblock %}
+{% block content %}
+<div class="tabBar">
+    <div class="headUsers">{% trans "Users" %}</div>
+    {{ users.paginator.sort_tabs }}
+</div>
+<div id="main-body" style="width:100%">
+    <p>        
+        {% if suser %}
+                       {% blocktrans %}users matching query {{suser}}:{% endblocktrans %}
+        {% endif %}
+    
+        {% if not users.paginator.count %}
+            <span>{% trans "Nothing found." %}</span>
+        {% endif %}
+    </p>
+    <div class="userList">
+        {% for user in users.paginator.page %}
+        <div class="user">
+            <ul>
+                <li class="thumb"><a href="{{ user.get_profile_url }} ">{% gravatar user 32 %}</a></li>
+                <li><a {% if user.is_suspended %}class="suspended-user" {% endif %}href="{{ user.get_profile_url }}">{{ user.decorated_name }}</a></li>
+                <li>{% get_score_badge user %}</li>
+            </ul>
+        </div>
+        {% endfor %}
+    </div>
+</div>
+{% endblock %}
+{% block tail %}
+<div class="pager">
+    {{ users.paginator.page_numbers }}
+</div>              
+{% endblock %}
+<!-- end users.html -->
diff --git a/forum/modules/template_loader.py/forum/skins/default/templates/users/votes.html b/forum/modules/template_loader.py/forum/skins/default/templates/users/votes.html
new file mode 100644 (file)
index 0000000..7d6b348
--- /dev/null
@@ -0,0 +1,28 @@
+{% extends "user.html" %}
+<!-- user_votes.html -->
+{% load extra_tags %}
+{% load extra_filters %}
+{% load humanize %}
+{% load i18n %}
+
+{% block usercontent %}
+        <div style="padding-top:5px;font-size:13px;">
+        {% for vote in votes %}
+            <div style="clear:both;line-height:20px" >
+                <div style="width:150px;float:left">{% diff_date vote.voted_at 3 %}</div>
+                <div style="width:30px;float:left">
+                {% ifequal vote.value 1 %}
+                    <img src="{% media  "/media/images/vote-arrow-up-on.png" %}" title="{% trans "upvote" %}">
+                {% else %}
+                    <img src="{% media  "/media/images/vote-arrow-down-on.png" %}" title="{% trans "downvote" %}">
+                {% endifequal %}
+                </div>
+                <div style="float:left;overflow:hidden;width:750px">
+                    <span class="{{ vote.node.node_type }}-title-link"><a href="{{ vote.node.get_absolute_url }}">{{ vote.node.headline }}</a></span>
+                    <div style="height:5px"></div>
+                </div>          
+            </div>
+        {% endfor %}
+        </div>
+{% endblock %}
+<!-- end user_votes.html -->
diff --git a/forum/modules/template_loader.py/forum/startup.py b/forum/modules/template_loader.py/forum/startup.py
new file mode 100644 (file)
index 0000000..9582a25
--- /dev/null
@@ -0,0 +1,16 @@
+import sys
+import os
+sys.path.append(os.path.join(os.path.dirname(__file__),'markdownext'))
+
+from forum.modules import get_modules_script
+
+get_modules_script('settings')
+get_modules_script('startup')
+
+
+import forum.badges
+import forum.subscriptions
+import forum.registry
+
+
+
diff --git a/forum/modules/template_loader.py/forum/subscriptions.py b/forum/modules/template_loader.py/forum/subscriptions.py
new file mode 100644 (file)
index 0000000..462e284
--- /dev/null
@@ -0,0 +1,179 @@
+import os\r
+import re\r
+import datetime\r
+import logging\r
+from forum.models import User, Question, Comment, QuestionSubscription, SubscriptionSettings, Answer\r
+from forum.utils.mail import send_template_email\r
+from django.utils.translation import ugettext as _\r
+from forum.actions import AskAction, AnswerAction, CommentAction, AcceptAnswerAction, UserJoinsAction, QuestionViewAction\r
+from forum import settings\r
+from django.db.models import Q, F\r
+\r
+def create_subscription_if_not_exists(question, user):\r
+    try:\r
+        subscription = QuestionSubscription.objects.get(question=question, user=user)\r
+    except:\r
+        subscription = QuestionSubscription(question=question, user=user)\r
+        subscription.save()\r
+\r
+def filter_subscribers(subscribers):\r
+    subscribers = subscribers.exclude(is_active=False)\r
+\r
+    if settings.DONT_NOTIFY_UNVALIDATED:\r
+        return subscribers.exclude(email_isvalid=False)\r
+    else:\r
+        return subscribers\r
+\r
+def question_posted(action, new):\r
+    question = action.node\r
+\r
+    subscribers = User.objects.filter(\r
+            Q(subscription_settings__enable_notifications=True, subscription_settings__new_question='i') |\r
+            (Q(subscription_settings__new_question_watched_tags='i') &\r
+              Q(marked_tags__name__in=question.tagnames.split(' ')) &\r
+              Q(tag_selections__reason='good'))\r
+    ).exclude(id=question.author.id).distinct()\r
+\r
+    subscribers = filter_subscribers(subscribers)\r
+\r
+    send_template_email(subscribers, "notifications/newquestion.html", {'question': question})\r
+\r
+    if question.author.subscription_settings.questions_asked:\r
+        subscription = QuestionSubscription(question=question, user=question.author)\r
+        subscription.save()\r
+\r
+    new_subscribers = User.objects.filter(\r
+            Q(subscription_settings__all_questions=True) |\r
+            Q(subscription_settings__all_questions_watched_tags=True,\r
+                    marked_tags__name__in=question.tagnames.split(' '),\r
+                    tag_selections__reason='good'))\r
+\r
+    for user in new_subscribers:\r
+        create_subscription_if_not_exists(question, user)\r
+\r
+AskAction.hook(question_posted)\r
+\r
+\r
+def answer_posted(action, new):\r
+    answer = action.node\r
+    question = answer.question\r
+\r
+    subscribers = question.subscribers.filter(\r
+            subscription_settings__enable_notifications=True,\r
+            subscription_settings__notify_answers=True,\r
+            subscription_settings__subscribed_questions='i'\r
+    ).exclude(id=answer.author.id).distinct()\r
+\r
+    subscribers = filter_subscribers(subscribers)\r
+\r
+    send_template_email(subscribers, "notifications/newanswer.html", {'answer': answer})\r
+\r
+    if answer.author.subscription_settings.questions_answered:\r
+        create_subscription_if_not_exists(question, answer.author)\r
+\r
+AnswerAction.hook(answer_posted)\r
+\r
+\r
+def comment_posted(action, new):\r
+    comment = action.node\r
+    post = comment.parent\r
+\r
+    if post.__class__ == Question:\r
+        question = post\r
+    else:\r
+        question = post.question\r
+\r
+    q_filter = Q(subscription_settings__notify_comments=True) | Q(subscription_settings__notify_comments_own_post=True, id=post.author.id)\r
+\r
+    inreply = re.search('@\w+', comment.comment)\r
+    if inreply is not None:\r
+        q_filter = q_filter | Q(subscription_settings__notify_reply_to_comments=True,\r
+                                username__istartswith=inreply.group(0)[1:],\r
+                                nodes__parent=post, nodes__node_type="comment")\r
+\r
+    subscribers = question.subscribers.filter(\r
+            q_filter, subscription_settings__subscribed_questions='i', subscription_settings__enable_notifications=True\r
+    ).exclude(id=comment.user.id).distinct()\r
+\r
+    subscribers = filter_subscribers(subscribers)\r
+\r
+\r
+    send_template_email(subscribers, "notifications/newcomment.html", {'comment': comment})\r
+\r
+    if comment.user.subscription_settings.questions_commented:\r
+        create_subscription_if_not_exists(question, comment.user)\r
+\r
+CommentAction.hook(comment_posted)\r
+\r
+\r
+def answer_accepted(action, new):\r
+    question = action.node.question\r
+\r
+    subscribers = question.subscribers.filter(\r
+            subscription_settings__enable_notifications=True,\r
+            subscription_settings__subscribed_questions='i'\r
+    ).exclude(id=action.node.nstate.accepted.by.id).distinct()\r
+    \r
+    subscribers = filter_subscribers(subscribers)\r
+\r
+    send_template_email(subscribers, "notifications/answeraccepted.html", {'answer': action.node})\r
+\r
+AcceptAnswerAction.hook(answer_accepted)\r
+\r
+\r
+def member_joined(action, new):\r
+    subscribers = User.objects.filter(\r
+            subscription_settings__enable_notifications=True,\r
+            subscription_settings__member_joins='i'\r
+    ).exclude(id=action.user.id).distinct()\r
+\r
+    subscribers = filter_subscribers(subscribers)\r
+\r
+    send_template_email(subscribers, "notifications/newmember.html", {'newmember': action.user})\r
+\r
+UserJoinsAction.hook(member_joined)\r
+\r
+def question_viewed(action, new):\r
+    if not action.viewuser.is_authenticated():\r
+        return\r
+\r
+    try:\r
+        subscription = QuestionSubscription.objects.get(question=action.node, user=action.viewuser)\r
+        subscription.last_view = datetime.datetime.now()\r
+        subscription.save()\r
+    except:\r
+        if action.viewuser.subscription_settings.questions_viewed:\r
+            subscription = QuestionSubscription(question=action.node, user=action.viewuser)\r
+            subscription.save()\r
+\r
+QuestionViewAction.hook(question_viewed)\r
+\r
+\r
+#todo: translate this\r
+#record_answer_event_re = re.compile("You have received (a|\d+) .*new response.*")\r
+#def record_answer_event(instance, created, **kwargs):\r
+#    if created:\r
+#        q_author = instance.question.author\r
+#        found_match = False\r
+#        #print 'going through %d messages' % q_author.message_set.all().count()\r
+#        for m in q_author.message_set.all():\r
+##            #print m.message\r
+# #           match = record_answer_event_re.search(m.message)\r
+#            if match:\r
+#                found_match = True\r
+#                try:\r
+#                    cnt = int(match.group(1))\r
+#                except:\r
+#                    cnt = 1\r
+##                m.message = u"You have received %d <a href=\"%s?sort=responses\">new responses</a>."\\r
+# #                           % (cnt+1, q_author.get_profile_url())\r
+#\r
+#                m.save()\r
+#                break\r
+#        if not found_match:\r
+#            msg = u"You have received a <a href=\"%s?sort=responses\">new response</a>."\\r
+#                    % q_author.get_profile_url()\r
+#\r
+#            q_author.message_set.create(message=msg)\r
+#\r
+#post_save.connect(record_answer_event, sender=Answer)\r
diff --git a/forum/modules/template_loader.py/forum/templatetags/__init__.py b/forum/modules/template_loader.py/forum/templatetags/__init__.py
new file mode 100644 (file)
index 0000000..56a0b8b
--- /dev/null
@@ -0,0 +1,7 @@
+import re\r
+\r
+splitter = re.compile(r'\s*=\s*')\r
+matcher = re.compile(r'^.+=.+$')\r
+\r
+def argument_parser(arguments):\r
+    return dict(splitter.split(s) for s in arguments if matcher.match(s))
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/templatetags/email_tags.py b/forum/modules/template_loader.py/forum/templatetags/email_tags.py
new file mode 100644 (file)
index 0000000..63b3a8d
--- /dev/null
@@ -0,0 +1,117 @@
+from django import template
+from forum import settings
+from forum.utils.mail import create_and_send_mail_messages
+from django.template.defaulttags import url as default_url
+
+register = template.Library()
+
+class MultiUserMailMessage(template.Node):
+    def __init__(self, nodelist):
+        self.nodelist = nodelist
+
+    def render(self, context):
+        recipients = context['recipients']
+        messages = list()
+
+        for recipient in recipients:
+            context['embeddedmedia'] = {}
+            context['recipient'] = recipient
+            self.nodelist.render(context)
+            messages.append((recipient, context['subject'], context['htmlcontent'], context['textcontent'], context['embeddedmedia']))
+
+        create_and_send_mail_messages(messages)
+
+@register.tag
+def email(parser, token):
+    nodelist = parser.parse(('endemail',))
+    parser.delete_first_token()
+    return MultiUserMailMessage(nodelist)
+
+
+
+class EmailPartNode(template.Node):
+    def __init__(self, nodelist, varname):
+        self.nodelist = nodelist
+        self.varname = varname
+
+    def render(self, context):
+        context[self.varname] = self.nodelist.render(context).strip()
+
+@register.tag
+def subject(parser, token):
+    nodelist = parser.parse(('endsubject',))
+    parser.delete_first_token()
+    return EmailPartNode(nodelist, 'subject')
+
+def content(parser, token):
+    try:
+        tag_name, base = token.split_contents()
+    except ValueError:
+        try:
+            tag_name = token.split_contents()[0]
+            base = None
+        except:
+            raise template.TemplateSyntaxError, "%r tag requires at least two arguments" % token.contents.split()[0]
+
+    nodelist = parser.parse(('end%s' % tag_name,))
+
+    if base:
+        base = template.loader.get_template(base)
+
+        basenodes = base.nodelist
+        content = [i for i,n in enumerate(basenodes) if isinstance(n, template.loader_tags.BlockNode) and n.name == "content"]
+        if len(content):
+            index = content[0]
+            nodelist = template.NodeList(basenodes[0:index] + nodelist + basenodes[index:])
+        
+
+    parser.delete_first_token()
+    return EmailPartNode(nodelist, tag_name)
+
+
+register.tag('htmlcontent', content)
+register.tag('textcontent', content)
+
+
+class EmbedMediaNode(template.Node):
+    def __init__(self, location, alias):
+        self.location = template.Variable(location)
+        self.alias = alias
+
+    def render(self, context):
+        context['embeddedmedia'][self.alias] = self.location.resolve(context)
+        pass
+
+
+@register.tag
+def embedmedia(parser, token):
+    try:
+        tag_name, location, _, alias = token.split_contents()
+    except ValueError:
+        raise template.TemplateSyntaxError, "%r tag requires exactly four arguments" % token.contents.split()[0]
+
+    return EmbedMediaNode(location, alias)
+
+
+class FullUrlNode(template.Node):
+    def __init__(self, default_node):
+        self.default_node = default_node
+
+    def render(self, context):
+        domain = settings.APP_BASE_URL
+        path = self.default_node.render(context)
+        return "%s%s" % (domain, path)
+
+@register.tag(name='fullurl')
+def fullurl(parser, token):
+    default_node = default_url(parser, token)
+    return FullUrlNode(default_node)
+
+
+
+
+
+    
+    
+
+
diff --git a/forum/modules/template_loader.py/forum/templatetags/extra_filters.py b/forum/modules/template_loader.py/forum/templatetags/extra_filters.py
new file mode 100644 (file)
index 0000000..e13923f
--- /dev/null
@@ -0,0 +1,58 @@
+from django import template
+from django.utils.safestring import mark_safe
+import logging
+import markdown
+
+register = template.Library()
+
+@template.defaultfilters.stringfilter
+@register.filter
+def collapse(input):
+    return ' '.join(input.split())
+
+
+@register.filter
+def can_edit_post(user, post):
+    return user.can_edit_post(post)
+
+
+@register.filter
+def decorated_int(number, cls="thousand"):
+    try:
+        number = int(number)    # allow strings or numbers passed in
+        if number > 999:
+            thousands = float(number) / 1000.0
+            format = "%.1f" if number < 99500 else "%.0f"
+            s = format % thousands
+
+            return mark_safe("<span class=\"%s\">%sk</span>" % (cls, s))
+        return number
+    except:
+        return number
+
+@register.filter
+def or_preview(setting, request):
+    if request.user.is_superuser:
+        previewing = request.session.get('previewing_settings', {})
+        if setting.name in previewing:
+            return previewing[setting.name]
+
+    return setting.value
+
+@register.filter
+def getval(map, key):
+    return map and map.get(key, None) or None
+
+
+@register.filter
+def contained_in(item, container):
+    return item in container
+
+@register.filter
+def static_content(content, render_mode):
+    if render_mode == 'markdown':
+        return mark_safe(markdown.markdown(unicode(content), ["settingsparser"]))
+    elif render_mode == "html":
+        return mark_safe(unicode(content))
+    else:
+        return unicode(content)
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/templatetags/extra_tags.py b/forum/modules/template_loader.py/forum/templatetags/extra_tags.py
new file mode 100644 (file)
index 0000000..76935fe
--- /dev/null
@@ -0,0 +1,251 @@
+import time
+import os
+import posixpath
+import datetime
+import math
+import re
+import logging
+from django import template
+from django.utils.encoding import smart_unicode
+from django.utils.safestring import mark_safe
+from forum.models import Question, Answer, QuestionRevision, AnswerRevision, NodeRevision
+from django.utils.translation import ugettext as _
+from django.utils.translation import ungettext
+from django.utils import simplejson
+from forum import settings
+from django.template.defaulttags import url as default_url
+from forum import skins
+from forum.utils import html
+from extra_filters import decorated_int
+from django.core.urlresolvers import reverse
+
+register = template.Library()
+
+GRAVATAR_TEMPLATE = ('<img class="gravatar" width="%(size)s" height="%(size)s" '
+'src="http://www.gravatar.com/avatar/%(gravatar_hash)s'
+'?s=%(size)s&amp;d=%(default)s&amp;r=%(rating)s" '
+'alt="%(username)s\'s gravatar image" />')
+
+@register.simple_tag
+def gravatar(user, size):
+    try:
+        gravatar = user['gravatar']
+        username = user['username']
+    except (TypeError, AttributeError, KeyError):
+        gravatar = user.gravatar
+        username = user.username
+    return mark_safe(GRAVATAR_TEMPLATE % {
+    'size': size,
+    'gravatar_hash': gravatar,
+    'default': settings.GRAVATAR_DEFAULT_IMAGE,
+    'rating': settings.GRAVATAR_ALLOWED_RATING,
+    'username': template.defaultfilters.urlencode(username),
+    })
+
+
+@register.simple_tag
+def get_score_badge(user):
+    if user.is_suspended():
+        return _("(suspended)")
+
+    repstr = decorated_int(user.reputation, "")
+
+    BADGE_TEMPLATE = '<span class="score" title="%(reputation)s %(reputationword)s">%(repstr)s</span>'
+    if user.gold > 0 :
+        BADGE_TEMPLATE = '%s%s' % (BADGE_TEMPLATE, '<span title="%(gold)s %(badgesword)s">'
+        '<span class="badge1">&#9679;</span>'
+        '<span class="badgecount">%(gold)s</span>'
+        '</span>')
+    if user.silver > 0:
+        BADGE_TEMPLATE = '%s%s' % (BADGE_TEMPLATE, '<span title="%(silver)s %(badgesword)s">'
+        '<span class="silver">&#9679;</span>'
+        '<span class="badgecount">%(silver)s</span>'
+        '</span>')
+    if user.bronze > 0:
+        BADGE_TEMPLATE = '%s%s' % (BADGE_TEMPLATE, '<span title="%(bronze)s %(badgesword)s">'
+        '<span class="bronze">&#9679;</span>'
+        '<span class="badgecount">%(bronze)s</span>'
+        '</span>')
+    BADGE_TEMPLATE = smart_unicode(BADGE_TEMPLATE, encoding='utf-8', strings_only=False, errors='strict')
+    return mark_safe(BADGE_TEMPLATE % {
+    'reputation' : user.reputation,
+    'repstr': repstr,
+    'gold' : user.gold,
+    'silver' : user.silver,
+    'bronze' : user.bronze,
+    'badgesword' : _('badges'),
+    'reputationword' : _('reputation points'),
+    })
+
+
+@register.simple_tag
+def get_age(birthday):
+    current_time = datetime.datetime(*time.localtime()[0:6])
+    year = birthday.year
+    month = birthday.month
+    day = birthday.day
+    diff = current_time - datetime.datetime(year, month, day, 0, 0, 0)
+    return diff.days / 365
+
+@register.simple_tag
+def diff_date(date, limen=2):
+    if not date:
+        return _('unknown')
+
+    now = datetime.datetime.now()
+    diff = now - date
+    days = diff.days
+    hours = int(diff.seconds/3600)
+    minutes = int(diff.seconds/60)
+
+    if days > 2:
+        if date.year == now.year:
+            return date.strftime(_("%b %d at %H:%M").encode())
+        else:
+            return date.strftime(_("%b %d '%y at %H:%M").encode())
+    elif days == 2:
+        return _('2 days ago')
+    elif days == 1:
+        return _('yesterday')
+    elif minutes >= 60:
+        return ungettext('%(hr)d ' + _("hour ago"), '%(hr)d ' + _("hours ago"), hours) % {'hr':hours}
+    elif diff.seconds >= 60:
+        return ungettext('%(min)d ' + _("min ago"), '%(min)d ' + _("mins ago"), minutes) % {'min':minutes}
+    else:
+        return ungettext('%(sec)d ' + _("sec ago"), '%(sec)d ' + _("secs ago"), diff.seconds) % {'sec':diff.seconds}
+
+@register.simple_tag
+def media(url):
+    url = skins.find_media_source(url)
+    if url:
+        # Create the URL prefix.
+        url_prefix = settings.FORCE_SCRIPT_NAME + '/m/'
+
+        # Make sure any duplicate forward slashes are replaced with a single
+        # forward slash.
+        url_prefix = re.sub("/+", "/", url_prefix)
+
+        url = url_prefix + url
+        return url
+
+class ItemSeparatorNode(template.Node):
+    def __init__(self, separator):
+        sep = separator.strip()
+        if sep[0] == sep[-1] and sep[0] in ('\'', '"'):
+            sep = sep[1:-1]
+        else:
+            raise template.TemplateSyntaxError('separator in joinitems tag must be quoted')
+        self.content = sep
+
+    def render(self, context):
+        return self.content
+
+class BlockMediaUrlNode(template.Node):
+    def __init__(self, nodelist):
+        self.items = nodelist
+
+    def render(self, context):
+        prefix = settings.APP_URL + 'm/'
+        url = ''
+        if self.items:
+            url += '/'
+        for item in self.items:
+            url += item.render(context)
+
+        url = skins.find_media_source(url)
+        url = prefix + url
+        out = url
+        return out.replace(' ', '')
+
+@register.tag(name='blockmedia')
+def blockmedia(parser, token):
+    try:
+        tagname = token.split_contents()
+    except ValueError:
+        raise template.TemplateSyntaxError("blockmedia tag does not use arguments")
+    nodelist = []
+    while True:
+        nodelist.append(parser.parse(('endblockmedia')))
+        next = parser.next_token()
+        if next.contents == 'endblockmedia':
+            break
+    return BlockMediaUrlNode(nodelist)
+
+
+@register.simple_tag
+def fullmedia(url):
+    domain = settings.APP_BASE_URL
+    #protocol = getattr(settings, "PROTOCOL", "http")
+    path = media(url)
+    return "%s%s" % (domain, path)
+
+
+class SimpleVarNode(template.Node):
+    def __init__(self, name, value):
+        self.name = name
+        self.value = template.Variable(value)
+
+    def render(self, context):
+        context[self.name] = self.value.resolve(context)
+        return ''
+
+class BlockVarNode(template.Node):
+    def __init__(self, name, block):
+        self.name = name
+        self.block = block
+
+    def render(self, context):
+        source = self.block.render(context)
+        context[self.name] = source.strip()
+        return ''
+
+
+@register.tag(name='var')
+def do_var(parser, token):
+    tokens = token.split_contents()[1:]
+
+    if not len(tokens) or not re.match('^\w+$', tokens[0]):
+        raise template.TemplateSyntaxError("Expected variable name")
+
+    if len(tokens) == 1:
+        nodelist = parser.parse(('endvar',))
+        parser.delete_first_token()
+        return BlockVarNode(tokens[0], nodelist)
+    elif len(tokens) == 3:
+        return SimpleVarNode(tokens[0], tokens[2])
+
+    raise template.TemplateSyntaxError("Invalid number of arguments")
+
+class DeclareNode(template.Node):
+    dec_re = re.compile('^\s*(\w+)\s*(:?=)\s*(.*)$')
+
+    def __init__(self, block):
+        self.block = block
+
+    def render(self, context):
+        source = self.block.render(context)
+
+        for line in source.splitlines():
+            m = self.dec_re.search(line)
+            if m:
+                clist = list(context)
+                clist.reverse()
+                d = {}
+                d['_'] = _
+                d['os'] = os
+                d['html'] = html
+                d['reverse'] = reverse
+                for c in clist:
+                    d.update(c)
+                try:
+                    context[m.group(1).strip()] = eval(m.group(3).strip(), d)
+                except Exception, e:
+                    logging.error("Error in declare tag, when evaluating: %s" % m.group(3).strip())
+                    raise
+        return ''
+
+@register.tag(name='declare')
+def do_declare(parser, token):
+    nodelist = parser.parse(('enddeclare',))
+    parser.delete_first_token()
+    return DeclareNode(nodelist)
diff --git a/forum/modules/template_loader.py/forum/templatetags/general_sidebar_tags.py b/forum/modules/template_loader.py/forum/templatetags/general_sidebar_tags.py
new file mode 100644 (file)
index 0000000..2f70fa2
--- /dev/null
@@ -0,0 +1,39 @@
+from django import template\r
+from forum.models import Tag, Award\r
+from forum import settings\r
+\r
+from extra_filters import static_content\r
+\r
+register = template.Library()\r
+\r
+@register.inclusion_tag('sidebar/markdown_help.html')\r
+def markdown_help():\r
+    return {}\r
+\r
+@register.inclusion_tag('sidebar/recent_awards.html')\r
+def recent_awards():\r
+    return {'awards': Award.objects.order_by('-awarded_at')[:settings.RECENT_AWARD_SIZE]}\r
+\r
+@register.inclusion_tag('sidebar/user_blocks.html')\r
+def sidebar_upper():\r
+    return {\r
+        'show': settings.SIDEBAR_UPPER_SHOW,\r
+        'content': static_content(settings.SIDEBAR_UPPER_TEXT, settings.SIDEBAR_UPPER_RENDER_MODE),\r
+        'wrap': not settings.SIDEBAR_UPPER_DONT_WRAP,\r
+        'blockid': 'sidebar-upper'\r
+    }\r
+\r
+@register.inclusion_tag('sidebar/user_blocks.html')\r
+def sidebar_lower():\r
+    return {\r
+        'show': settings.SIDEBAR_LOWER_SHOW,\r
+        'content': static_content(settings.SIDEBAR_LOWER_TEXT, settings.SIDEBAR_LOWER_RENDER_MODE),\r
+        'wrap': not settings.SIDEBAR_LOWER_DONT_WRAP,\r
+        'blockid': 'sidebar-lower'\r
+    }\r
+\r
+@register.inclusion_tag('sidebar/recent_tags.html')\r
+def recent_tags():\r
+    return {'tags': Tag.active.order_by('-id')[:settings.RECENT_TAGS_SIZE]}\r
+\r
+    
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/templatetags/node_tags.py b/forum/modules/template_loader.py/forum/templatetags/node_tags.py
new file mode 100644 (file)
index 0000000..720f822
--- /dev/null
@@ -0,0 +1,215 @@
+from datetime import datetime, timedelta\r
+import re\r
+\r
+from forum.models import Question, Action\r
+from django.utils.translation import ungettext, ugettext as _\r
+from django.utils.html import strip_tags\r
+from django.utils.safestring import mark_safe\r
+from django.core.urlresolvers import reverse\r
+from django import template\r
+from forum.actions import *\r
+from forum import settings\r
+\r
+register = template.Library()\r
+\r
+@register.inclusion_tag('node/vote_buttons.html')\r
+def vote_buttons(post, user):\r
+    context = dict(post=post, user_vote='none')\r
+\r
+    if user.is_authenticated():\r
+        context['user_vote'] = {1: 'up', -1: 'down', None: 'none'}[VoteAction.get_for(user, post)]\r
+\r
+    return context\r
+\r
+@register.inclusion_tag('node/accept_button.html')\r
+def accept_button(answer, user):\r
+    if not settings.DISABLE_ACCEPTING_FEATURE:\r
+        return {\r
+            'can_accept': user.is_authenticated() and user.can_accept_answer(answer),\r
+            'answer': answer,\r
+            'user': user\r
+        }\r
+    else:\r
+        return ''\r
+\r
+@register.inclusion_tag('node/wiki_symbol.html')\r
+def wiki_symbol(user, post):\r
+    context = {\r
+        'is_wiki': post.nis.wiki,\r
+        'post_type': post.friendly_name\r
+    }\r
+\r
+    if post.nis.wiki:\r
+        if user.can_edit_post(post):\r
+            context['can_edit'] = True\r
+            context['edit_url'] = reverse('edit_' + post.node_type, kwargs={'id': post.id})\r
+        context['by'] = post.nstate.wiki.by.username\r
+        context['at'] = post.nstate.wiki.at\r
+\r
+    return context\r
+\r
+@register.inclusion_tag('node/favorite_mark.html')\r
+def favorite_mark(question, user):\r
+    try:\r
+        FavoriteAction.objects.get(canceled=False, node=question, user=user)\r
+        favorited = True\r
+    except:\r
+        favorited = False\r
+\r
+    return {'favorited': favorited, 'favorite_count': question.favorite_count, 'question': question}\r
+\r
+@register.simple_tag\r
+def post_classes(post):\r
+    classes = []\r
+\r
+    if post.nis.deleted:\r
+        classes.append('deleted')\r
+\r
+    if post.node_type == "answer":\r
+        if (not settings.DISABLE_ACCEPTING_FEATURE) and post.nis.accepted:\r
+            classes.append('accepted-answer')\r
+\r
+        if post.author == post.question.author:\r
+            classes.append('answered-by-owner')\r
+\r
+    return " ".join(classes)\r
+\r
+def post_control(text, url, command=False, withprompt=False, confirm=False, title=""):\r
+    classes = (command and "ajax-command" or " ") + (withprompt and " withprompt" or " ") + (confirm and " confirm" or " ")\r
+    return {'text': text, 'url': url, 'classes': classes, 'title': title}\r
+\r
+@register.inclusion_tag('node/post_controls.html')\r
+def post_controls(post, user):\r
+    controls = []\r
+    menu = []\r
+\r
+    if user.is_authenticated():\r
+        post_type = post.node_type\r
+\r
+        if post_type == "answer":\r
+            controls.append(post_control(_('permanent link'), post.get_absolute_url(), title=_("answer permanent link")))\r
+\r
+        edit_url = reverse('edit_' + post_type, kwargs={'id': post.id})\r
+        if user.can_edit_post(post):\r
+            controls.append(post_control(_('edit'), edit_url))\r
+        elif post_type == 'question' and user.can_retag_questions():\r
+            controls.append(post_control(_('retag'), edit_url))\r
+\r
+        if post_type == 'question':\r
+            if post.nis.closed and user.can_reopen_question(post):\r
+                controls.append(post_control(_('reopen'), reverse('reopen', kwargs={'id': post.id}), command=True))\r
+            elif not post.nis.closed and user.can_close_question(post):\r
+                controls.append(post_control(_('close'), reverse('close', kwargs={'id': post.id}), command=True, withprompt=True))\r
+\r
+        if user.can_flag_offensive(post):\r
+            label = _('report')\r
+            \r
+            if user.can_view_offensive_flags(post):\r
+                label =  "%s (%d)" % (label, post.flag_count)\r
+\r
+            controls.append(post_control(label, reverse('flag_post', kwargs={'id': post.id}),\r
+                    command=True, withprompt=True, title=_("report as offensive (i.e containing spam, advertising, malicious text, etc.)")))\r
+\r
+        if user.can_delete_post(post):\r
+            if post.nis.deleted:\r
+                controls.append(post_control(_('undelete'), reverse('delete_post', kwargs={'id': post.id}),\r
+                        command=True, confirm=True))\r
+            else:\r
+                controls.append(post_control(_('delete'), reverse('delete_post', kwargs={'id': post.id}),\r
+                        command=True, confirm=True))\r
+\r
+        if user.can_delete_post(post):\r
+            menu.append(post_control(_('see revisions'),\r
+                        reverse('revisions',\r
+                        kwargs={'id': post.id}),\r
+                        command=False, confirm=False))\r
+\r
+        if settings.WIKI_ON:\r
+            if (not post.nis.wiki) and user.can_wikify(post):\r
+                menu.append(post_control(_('mark as community wiki'), reverse('wikify', kwargs={'id': post.id}),\r
+                            command=True, confirm=True))\r
+\r
+            elif post.nis.wiki and user.can_cancel_wiki(post):\r
+                menu.append(post_control(_('cancel community wiki'), reverse('wikify', kwargs={'id': post.id}),\r
+                            command=True, confirm=True))\r
+\r
+        if post.node_type == "answer" and user.can_convert_to_comment(post):\r
+            menu.append(post_control(_('convert to comment'), reverse('convert_to_comment', kwargs={'id': post.id}),\r
+                        command=True, withprompt=True))\r
+        \r
+        if post.node_type == "answer" and user.can_convert_to_question(post):\r
+            menu.append(post_control(_('convert to question'), reverse('convert_to_question', kwargs={'id': post.id}),\r
+                        command=True, withprompt=True))\r
+\r
+        if user.is_superuser or user.is_staff:\r
+            plain_text = strip_tags(post.html)\r
+\r
+            char_count = len(plain_text)\r
+            fullStr = plain_text + " "\r
+            left_trimmedStr = re.sub(re.compile(r"^[^\w]+", re.IGNORECASE), "", fullStr)\r
+            cleanedStr = re.sub(re.compile(r"[^\w]+", re.IGNORECASE), " ", left_trimmedStr)\r
+            splitString = cleanedStr.split(" ")\r
+            word_count = len(splitString) - 1\r
+\r
+            metrics = mark_safe("<b>%s %s / %s %s</b>" % (char_count, ungettext('character', 'characters', char_count),\r
+                                        word_count, ungettext('word', 'words', word_count)))\r
+\r
+            menu.append(post_control(metrics, "#", command=False, withprompt=False))\r
+\r
+    return {'controls': controls, 'menu': menu, 'post': post, 'user': user}\r
+\r
+@register.inclusion_tag('node/comments.html')\r
+def comments(post, user):\r
+    all_comments = post.comments.filter_state(deleted=False).order_by('added_at')\r
+\r
+    if len(all_comments) <= 5:\r
+        top_scorers = all_comments\r
+    else:\r
+        top_scorers = sorted(all_comments, lambda c1, c2: cmp(c2.score, c1.score))[0:5]\r
+\r
+    comments = []\r
+    showing = 0\r
+    for c in all_comments:\r
+        context = {\r
+            'can_delete': user.can_delete_comment(c),\r
+            'can_like': user.can_like_comment(c),\r
+            'can_edit': user.can_edit_comment(c),\r
+            'can_convert': user.can_convert_comment_to_answer(c)\r
+        }\r
+\r
+        if c in top_scorers or c.is_reply_to(user):\r
+            context['top_scorer'] = True\r
+            showing += 1\r
+        \r
+        if context['can_like']:\r
+            context['likes'] = VoteAction.get_for(user, c) == 1\r
+\r
+        context['user'] = c.user\r
+        context['comment'] = c.comment\r
+        context.update(dict(c.__dict__))\r
+        comments.append(context)\r
+\r
+    return {\r
+        'comments': comments,\r
+        'post': post,\r
+        'can_comment': user.can_comment(post),\r
+        'max_length': settings.FORM_MAX_COMMENT_BODY,\r
+        'min_length': settings.FORM_MIN_COMMENT_BODY,\r
+        'show_gravatar': settings.FORM_GRAVATAR_IN_COMMENTS,\r
+        'showing': showing,\r
+        'total': len(all_comments),\r
+        'user': user,\r
+    }\r
+\r
+\r
+@register.inclusion_tag("node/contributors_info.html")\r
+def contributors_info(node):\r
+    return {\r
+        'node_verb': (node.node_type == "question") and _("asked") or (\r
+                    (node.node_type == "answer") and _("answered") or _("posted")),\r
+        'node': node,\r
+    }\r
+\r
+@register.inclusion_tag("node/reviser_info.html")\r
+def reviser_info(revision):\r
+    return {'revision': revision}\r
diff --git a/forum/modules/template_loader.py/forum/templatetags/question_list_tags.py b/forum/modules/template_loader.py/forum/templatetags/question_list_tags.py
new file mode 100644 (file)
index 0000000..3ecf1f6
--- /dev/null
@@ -0,0 +1,77 @@
+from django import template\r
+from django.utils.translation import ugettext as _\r
+from django.utils.safestring import mark_safe\r
+from forum.models import Tag, MarkedTag\r
+from forum.templatetags import argument_parser\r
+from forum import settings\r
+\r
+register = template.Library()\r
+\r
+class QuestionItemNode(template.Node):\r
+    template = template.loader.get_template('question_list/item.html')\r
+\r
+    def __init__(self, question, options):\r
+        self.question = template.Variable(question)\r
+        self.options = options\r
+\r
+    def render(self, context):\r
+        return self.template.render(template.Context({\r
+            'question': self.question.resolve(context),\r
+            'favorite_count': self.options.get('favorite_count', 'no') == 'yes',\r
+            'signature_type': self.options.get('signature_type', 'lite'),\r
+        }))\r
+\r
+class SubscriptionItemNode(template.Node):\r
+    template = template.loader.get_template('question_list/subscription_item.html')\r
+\r
+    def __init__(self, subscription, question, options):\r
+        self.question = template.Variable(question)\r
+        self.subscription = template.Variable(subscription)\r
+        self.options = options\r
+\r
+    def render(self, context):\r
+        return self.template.render(template.Context({\r
+            'question': self.question.resolve(context),\r
+            'subscription': self.subscription.resolve(context),\r
+            'signature_type': self.options.get('signature_type', 'lite'),\r
+        }))\r
+\r
+@register.tag\r
+def question_list_item(parser, token):\r
+    tokens = token.split_contents()[1:]\r
+    return QuestionItemNode(tokens[0], argument_parser(tokens[1:]))\r
+\r
+@register.tag\r
+def subscription_list_item(parser, token):\r
+    tokens = token.split_contents()[1:]\r
+    return SubscriptionItemNode(tokens[0], tokens[1], argument_parser(tokens[2:]))\r
+\r
+@register.inclusion_tag('question_list/sort_tabs.html')\r
+def question_sort_tabs(sort_context):\r
+    return sort_context\r
+\r
+@register.inclusion_tag('question_list/related_tags.html')\r
+def question_list_related_tags(questions):\r
+    if len(questions):\r
+        tags = Tag.objects.filter(nodes__id__in=[q.id for q in questions]).distinct()\r
+\r
+        if settings.LIMIT_RELATED_TAGS:\r
+            tags = tags[:settings.LIMIT_RELATED_TAGS]\r
+\r
+        return {'tags': tags}\r
+    else:\r
+        return {'tags': False}\r
+\r
+@register.inclusion_tag('question_list/tag_selector.html', takes_context=True)\r
+def tag_selector(context):\r
+    request = context['request']\r
+\r
+    if request.user.is_authenticated():\r
+        pt = MarkedTag.objects.filter(user=request.user)\r
+        return {\r
+            "interesting_tag_names": pt.filter(reason='good').values_list('tag__name', flat=True),\r
+            'ignored_tag_names': pt.filter(reason='bad').values_list('tag__name', flat=True),\r
+            'user_authenticated': True,\r
+        }\r
+    else:\r
+        return {'user_authenticated': False}\r
diff --git a/forum/modules/template_loader.py/forum/templatetags/smart_if.py b/forum/modules/template_loader.py/forum/templatetags/smart_if.py
new file mode 100644 (file)
index 0000000..ca3b43f
--- /dev/null
@@ -0,0 +1,401 @@
+"""
+A smarter {% if %} tag for django templates.
+
+While retaining current Django functionality, it also handles equality,
+greater than and less than operators. Some common case examples::
+
+    {% if articles|length >= 5 %}...{% endif %}
+    {% if "ifnotequal tag" != "beautiful" %}...{% endif %}
+"""
+import unittest
+from django import template
+
+
+register = template.Library()
+
+
+#==============================================================================
+# Calculation objects
+#==============================================================================
+
+class BaseCalc(object):
+    def __init__(self, var1, var2=None, negate=False):
+        self.var1 = var1
+        self.var2 = var2
+        self.negate = negate
+
+    def resolve(self, context):
+        try:
+            var1, var2 = self.resolve_vars(context)
+            outcome = self.calculate(var1, var2)
+        except:
+            outcome = False
+        if self.negate:
+            return not outcome
+        return outcome
+
+    def resolve_vars(self, context):
+        var2 = self.var2 and self.var2.resolve(context)
+        return self.var1.resolve(context), var2
+
+    def calculate(self, var1, var2):
+        raise NotImplementedError()
+
+
+class Or(BaseCalc):
+    def calculate(self, var1, var2):
+        return var1 or var2
+
+
+class And(BaseCalc):
+    def calculate(self, var1, var2):
+        return var1 and var2
+
+
+class Equals(BaseCalc):
+    def calculate(self, var1, var2):
+        return var1 == var2
+
+
+class Greater(BaseCalc):
+    def calculate(self, var1, var2):
+        return var1 > var2
+
+
+class GreaterOrEqual(BaseCalc):
+    def calculate(self, var1, var2):
+        return var1 >= var2
+
+
+class In(BaseCalc):
+    def calculate(self, var1, var2):
+        return var1 in var2
+
+
+#==============================================================================
+# Tests
+#==============================================================================
+
+class TestVar(object):
+    """
+    A basic self-resolvable object similar to a Django template variable. Used
+    to assist with tests.
+    """
+    def __init__(self, value):
+        self.value = value
+
+    def resolve(self, context):
+        return self.value
+
+
+class SmartIfTests(unittest.TestCase):
+    def setUp(self):
+        self.true = TestVar(True)
+        self.false = TestVar(False)
+        self.high = TestVar(9000)
+        self.low = TestVar(1)
+
+    def assertCalc(self, calc, context=None):
+        """
+        Test a calculation is True, also checking the inverse "negate" case.
+        """
+        context = context or {}
+        self.assert_(calc.resolve(context))
+        calc.negate = not calc.negate
+        self.assertFalse(calc.resolve(context))
+
+    def assertCalcFalse(self, calc, context=None):
+        """
+        Test a calculation is False, also checking the inverse "negate" case.
+        """
+        context = context or {}
+        self.assertFalse(calc.resolve(context))
+        calc.negate = not calc.negate
+        self.assert_(calc.resolve(context))
+
+    def test_or(self):
+        self.assertCalc(Or(self.true))
+        self.assertCalcFalse(Or(self.false))
+        self.assertCalc(Or(self.true, self.true))
+        self.assertCalc(Or(self.true, self.false))
+        self.assertCalc(Or(self.false, self.true))
+        self.assertCalcFalse(Or(self.false, self.false))
+
+    def test_and(self):
+        self.assertCalc(And(self.true, self.true))
+        self.assertCalcFalse(And(self.true, self.false))
+        self.assertCalcFalse(And(self.false, self.true))
+        self.assertCalcFalse(And(self.false, self.false))
+
+    def test_equals(self):
+        self.assertCalc(Equals(self.low, self.low))
+        self.assertCalcFalse(Equals(self.low, self.high))
+
+    def test_greater(self):
+        self.assertCalc(Greater(self.high, self.low))
+        self.assertCalcFalse(Greater(self.low, self.low))
+        self.assertCalcFalse(Greater(self.low, self.high))
+
+    def test_greater_or_equal(self):
+        self.assertCalc(GreaterOrEqual(self.high, self.low))
+        self.assertCalc(GreaterOrEqual(self.low, self.low))
+        self.assertCalcFalse(GreaterOrEqual(self.low, self.high))
+
+    def test_in(self):
+        list_ = TestVar([1,2,3])
+        invalid_list = TestVar(None)
+        self.assertCalc(In(self.low, list_))
+        self.assertCalcFalse(In(self.low, invalid_list))
+
+    def test_parse_bits(self):
+        var = IfParser([True]).parse()
+        self.assert_(var.resolve({}))
+        var = IfParser([False]).parse()
+        self.assertFalse(var.resolve({}))
+
+        var = IfParser([False, 'or', True]).parse()
+        self.assert_(var.resolve({}))
+
+        var = IfParser([False, 'and', True]).parse()
+        self.assertFalse(var.resolve({}))
+
+        var = IfParser(['not', False, 'and', 'not', False]).parse()
+        self.assert_(var.resolve({}))
+
+        var = IfParser(['not', 'not', True]).parse()
+        self.assert_(var.resolve({}))
+
+        var = IfParser([1, '=', 1]).parse()
+        self.assert_(var.resolve({}))
+
+        var = IfParser([1, 'not', '=', 1]).parse()
+        self.assertFalse(var.resolve({}))
+
+        var = IfParser([1, 'not', 'not', '=', 1]).parse()
+        self.assert_(var.resolve({}))
+
+        var = IfParser([1, '!=', 1]).parse()
+        self.assertFalse(var.resolve({}))
+
+        var = IfParser([3, '>', 2]).parse()
+        self.assert_(var.resolve({}))
+
+        var = IfParser([1, '<', 2]).parse()
+        self.assert_(var.resolve({}))
+
+        var = IfParser([2, 'not', 'in', [2, 3]]).parse()
+        self.assertFalse(var.resolve({}))
+
+        var = IfParser([1, 'or', 1, '=', 2]).parse()
+        self.assert_(var.resolve({}))
+
+    def test_boolean(self):
+        var = IfParser([True, 'and', True, 'and', True]).parse()
+        self.assert_(var.resolve({}))
+        var = IfParser([False, 'or', False, 'or', True]).parse()
+        self.assert_(var.resolve({}))
+        var = IfParser([True, 'and', False, 'or', True]).parse()
+        self.assert_(var.resolve({}))
+        var = IfParser([False, 'or', True, 'and', True]).parse()
+        self.assert_(var.resolve({}))
+
+        var = IfParser([True, 'and', True, 'and', False]).parse()
+        self.assertFalse(var.resolve({}))
+        var = IfParser([False, 'or', False, 'or', False]).parse()
+        self.assertFalse(var.resolve({}))
+        var = IfParser([False, 'or', True, 'and', False]).parse()
+        self.assertFalse(var.resolve({}))
+        var = IfParser([False, 'and', True, 'or', False]).parse()
+        self.assertFalse(var.resolve({}))
+
+    def test_invalid(self):
+        self.assertRaises(ValueError, IfParser(['not']).parse)
+        self.assertRaises(ValueError, IfParser(['==']).parse)
+        self.assertRaises(ValueError, IfParser([1, 'in']).parse)
+        self.assertRaises(ValueError, IfParser([1, '>', 'in']).parse)
+        self.assertRaises(ValueError, IfParser([1, '==', 'not', 'not']).parse)
+        self.assertRaises(ValueError, IfParser([1, 2]).parse)
+
+
+OPERATORS = {
+    '=': (Equals, True),
+    '==': (Equals, True),
+    '!=': (Equals, False),
+    '>': (Greater, True),
+    '>=': (GreaterOrEqual, True),
+    '<=': (Greater, False),
+    '<': (GreaterOrEqual, False),
+    'or': (Or, True),
+    'and': (And, True),
+    'in': (In, True),
+}
+BOOL_OPERATORS = ('or', 'and')
+
+
+class IfParser(object):
+    error_class = ValueError
+
+    def __init__(self, tokens):
+        self.tokens = tokens
+
+    def _get_tokens(self):
+        return self._tokens
+
+    def _set_tokens(self, tokens):
+        self._tokens = tokens
+        self.len = len(tokens)
+        self.pos = 0
+
+    tokens = property(_get_tokens, _set_tokens)
+
+    def parse(self):
+        if self.at_end():
+            raise self.error_class('No variables provided.')
+        var1 = self.get_bool_var()
+        while not self.at_end():
+            op, negate = self.get_operator()
+            var2 = self.get_bool_var()
+            var1 = op(var1, var2, negate=negate)
+        return var1
+
+    def get_token(self, eof_message=None, lookahead=False):
+        negate = True
+        token = None
+        pos = self.pos
+        while token is None or token == 'not':
+            if pos >= self.len:
+                if eof_message is None:
+                    raise self.error_class()
+                raise self.error_class(eof_message)
+            token = self.tokens[pos]
+            negate = not negate
+            pos += 1
+        if not lookahead:
+            self.pos = pos
+        return token, negate
+
+    def at_end(self):
+        return self.pos >= self.len
+
+    def create_var(self, value):
+        return TestVar(value)
+
+    def get_bool_var(self):
+        """
+        Returns either a variable by itself or a non-boolean operation (such as
+        ``x == 0`` or ``x < 0``).
+
+        This is needed to keep correct precedence for boolean operations (i.e.
+        ``x or x == 0`` should be ``x or (x == 0)``, not ``(x or x) == 0``).
+        """
+        var = self.get_var()
+        if not self.at_end():
+            op_token = self.get_token(lookahead=True)[0]
+            if isinstance(op_token, basestring) and (op_token not in
+                                                     BOOL_OPERATORS):
+                op, negate = self.get_operator()
+                return op(var, self.get_var(), negate=negate)
+        return var
+
+    def get_var(self):
+        token, negate = self.get_token('Reached end of statement, still '
+                                       'expecting a variable.')
+        if isinstance(token, basestring) and token in OPERATORS:
+            raise self.error_class('Expected variable, got operator (%s).' %
+                                   token)
+        var = self.create_var(token)
+        if negate:
+            return Or(var, negate=True)
+        return var
+
+    def get_operator(self):
+        token, negate = self.get_token('Reached end of statement, still '
+                                       'expecting an operator.')
+        if not isinstance(token, basestring) or token not in OPERATORS:
+            raise self.error_class('%s is not a valid operator.' % token)
+        if self.at_end():
+            raise self.error_class('No variable provided after "%s".' % token)
+        op, true = OPERATORS[token]
+        if not true:
+            negate = not negate
+        return op, negate
+
+
+#==============================================================================
+# Actual templatetag code.
+#==============================================================================
+
+class TemplateIfParser(IfParser):
+    error_class = template.TemplateSyntaxError
+
+    def __init__(self, parser, *args, **kwargs):
+        self.template_parser = parser
+        return super(TemplateIfParser, self).__init__(*args, **kwargs)
+
+    def create_var(self, value):
+        return self.template_parser.compile_filter(value)
+
+
+class SmartIfNode(template.Node):
+    def __init__(self, var, nodelist_true, nodelist_false=None):
+        self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false
+        self.var = var
+
+    def render(self, context):
+        if self.var.resolve(context):
+            return self.nodelist_true.render(context)
+        if self.nodelist_false:
+            return self.nodelist_false.render(context)
+        return ''
+
+    def __repr__(self):
+        return "<Smart If node>"
+
+    def __iter__(self):
+        for node in self.nodelist_true:
+            yield node
+        if self.nodelist_false:
+            for node in self.nodelist_false:
+                yield node
+
+    def get_nodes_by_type(self, nodetype):
+        nodes = []
+        if isinstance(self, nodetype):
+            nodes.append(self)
+        nodes.extend(self.nodelist_true.get_nodes_by_type(nodetype))
+        if self.nodelist_false:
+            nodes.extend(self.nodelist_false.get_nodes_by_type(nodetype))
+        return nodes
+
+
+@register.tag('if')
+def smart_if(parser, token):
+    """
+    A smarter {% if %} tag for django templates.
+
+    While retaining current Django functionality, it also handles equality,
+    greater than and less than operators. Some common case examples::
+
+        {% if articles|length >= 5 %}...{% endif %}
+        {% if "ifnotequal tag" != "beautiful" %}...{% endif %}
+
+    Arguments and operators _must_ have a space between them, so
+    ``{% if 1>2 %}`` is not a valid smart if tag.
+
+    All supported operators are: ``or``, ``and``, ``in``, ``=`` (or ``==``),
+    ``!=``, ``>``, ``>=``, ``<`` and ``<=``.
+    """
+    bits = token.split_contents()[1:]
+    var = TemplateIfParser(parser, bits).parse()
+    nodelist_true = parser.parse(('else', 'endif'))
+    token = parser.next_token()
+    if token.contents == 'else':
+        nodelist_false = parser.parse(('endif',))
+        parser.delete_first_token()
+    else:
+        nodelist_false = None
+    return SmartIfNode(var, nodelist_true, nodelist_false)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/forum/modules/template_loader.py/forum/templatetags/ui_registry.py b/forum/modules/template_loader.py/forum/templatetags/ui_registry.py
new file mode 100644 (file)
index 0000000..21ba3bb
--- /dev/null
@@ -0,0 +1,78 @@
+from django import template
+from forum.modules import ui
+import logging
+
+register = template.Library()
+
+
+class LoadRegistryNode(template.Node):
+    def __init__(self, registry, separator):
+        self.registry = registry
+        self.separator = separator
+
+    def render(self, context):
+        separator = self.separator.render(context)
+        result = ''
+
+        for ui_object in self.registry:
+            try:
+                if ui_object.can_render(context):
+                        if result:
+                            result += separator
+                        result += ui_object.render(context)
+            except (KeyError, Exception), e:
+                import traceback
+                logging.error("Exception %s rendering ui objects %s: \n%s" % (
+                    e, ui_object, traceback.format_exc()
+                ))
+
+        return result
+
+
+@register.tag
+def loadregistry(parser, token):
+    try:
+        tag_name, registry = token.split_contents()
+    except ValueError:
+        raise template.TemplateSyntaxError, "%r tag requires exactly one argument" % token.contents.split()[0]
+
+    registry = ui.get_registry_by_name(registry)
+    separator = parser.parse(('endloadregistry',))
+    parser.delete_first_token()
+    return LoadRegistryNode(registry, separator)
+
+
+class LoopRegistryNode(template.Node):
+    def __init__(self, registry, nodelist):
+        self.registry = registry
+        self.nodelist = nodelist
+
+    def render(self, context):
+        result = ''
+
+        for ui_object in self.registry:
+            if ui_object.can_render(context):
+                try:
+                    ui_object.update_context(context)
+                    result += self.nodelist.render(context)
+                except Exception, e:
+                    import traceback
+                    logging.error("Exception %s updating ui loop context %s: \n%s" % (
+                        e, ui_object, traceback.format_exc()
+                    ))
+
+
+        return result
+
+@register.tag
+def loopregistry(parser, token):
+    try:
+        tag_name, registry = token.split_contents()
+    except ValueError:
+        raise template.TemplateSyntaxError, "%r tag requires exactly one argument" % token.contents.split()[0]
+
+    registry = ui.get_registry_by_name(registry)
+    nodelist = parser.parse(('endloopregistry',))
+    parser.delete_first_token()
+
+    return LoopRegistryNode(registry, nodelist)
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/templatetags/user_tags.py b/forum/modules/template_loader.py/forum/templatetags/user_tags.py
new file mode 100644 (file)
index 0000000..b0f2b61
--- /dev/null
@@ -0,0 +1,71 @@
+from django import template\r
+from django.utils.translation import ugettext as _\r
+from django.utils.safestring import mark_safe\r
+import logging\r
+\r
+register = template.Library()\r
+\r
+class UserSignatureNode(template.Node):\r
+    template = template.loader.get_template('users/signature.html')\r
+\r
+    def __init__(self, user, format):\r
+        self.user = template.Variable(user)\r
+        self.format = template.Variable(format)\r
+\r
+    def render(self, context):\r
+        return self.template.render(template.Context({\r
+        'user': self.user.resolve(context),\r
+        'format': self.format.resolve(context)\r
+        }))\r
+\r
+@register.tag\r
+def user_signature(parser, token):\r
+    try:\r
+        tag_name, user, format = token.split_contents()\r
+    except ValueError:\r
+        raise template.TemplateSyntaxError, "%r tag requires exactly two arguments" % token.contents.split()[0]\r
+\r
+    return UserSignatureNode(user, format)\r
+\r
+\r
+class ActivityNode(template.Node):\r
+    template = template.loader.get_template('users/activity.html')\r
+\r
+    def __init__(self, activity, viewer):\r
+        self.activity = template.Variable(activity)\r
+        self.viewer = template.Variable(viewer)\r
+\r
+    def render(self, context):\r
+        try:\r
+            action = self.activity.resolve(context).leaf()\r
+            viewer = self.viewer.resolve(context)\r
+            describe = mark_safe(action.describe(viewer))\r
+            return self.template.render(template.Context(dict(action=action, describe=describe)))\r
+        except Exception, e:\r
+            #return action.action_type + ":" + str(e)\r
+            logging.error("Error in %s action describe: %s" % (action.action_type, str(e)))\r
+\r
+@register.tag\r
+def activity_item(parser, token):\r
+    try:\r
+        tag_name, activity, viewer = token.split_contents()\r
+    except ValueError:\r
+        raise template.TemplateSyntaxError, "%r tag requires exactly two arguments" % token.contents.split()[0]\r
+\r
+    return ActivityNode(activity, viewer)\r
+\r
+\r
+@register.tag\r
+def flagged_item(parser, token):\r
+    try:\r
+        tag_name, post, viewer = token.split_contents()\r
+    except ValueError:\r
+        raise template.TemplateSyntaxError, "%r tag requires exactly two arguments" % token.contents.split()[0]\r
+\r
+    return ActivityNode(post, viewer)\r
+\r
+\r
+@register.inclusion_tag('users/menu.html')\r
+def user_menu(viewer, user):\r
+    return dict(viewer=viewer, user=user)\r
+\r
diff --git a/forum/modules/template_loader.py/forum/upfiles/README b/forum/modules/template_loader.py/forum/upfiles/README
new file mode 100644 (file)
index 0000000..17bf8ec
--- /dev/null
@@ -0,0 +1,2 @@
+This directory is to contain uploaded images and other files
+must be writable by the webserver
diff --git a/forum/modules/template_loader.py/forum/upfiles/logo.png b/forum/modules/template_loader.py/forum/upfiles/logo.png
new file mode 100644 (file)
index 0000000..bb1b829
Binary files /dev/null and b/forum/modules/template_loader.py/forum/upfiles/logo.png differ
diff --git a/forum/modules/template_loader.py/forum/urls.py b/forum/modules/template_loader.py/forum/urls.py
new file mode 100644 (file)
index 0000000..1771e2c
--- /dev/null
@@ -0,0 +1,216 @@
+import startup
+
+import os.path
+from forum import settings
+from django.conf.urls.defaults import *
+from django.conf import settings as djsettings
+from django.contrib import admin
+from forum import views as app
+from forum.sitemap import OsqaSitemap
+from django.utils.translation import ugettext as _
+import logging
+
+admin.autodiscover()
+
+sitemaps = {
+    'questions': OsqaSitemap
+}
+
+APP_PATH = os.path.dirname(__file__)
+
+from forum.modules import get_modules_script
+
+module_patterns = get_modules_script('urls')
+
+urlpatterns = patterns('')
+
+for pattern_file in module_patterns:
+    pattern = getattr(pattern_file, 'urlpatterns', None)
+    if pattern:
+        urlpatterns += pattern
+
+urlpatterns += patterns('',
+                        url(r'^$', app.readers.index, name='index'),
+                        url(r'^%s(.*)' % _('nimda/'), admin.site.root),
+                        
+                        url(r'^sitemap.xml$', 'forum.sitemap.index', {'sitemaps': sitemaps}),
+                        url(r'^sitemap-(?P<section>.+)\.xml$', 'forum.sitemap.sitemap', {'sitemaps': sitemaps}),
+
+                        (r'^favicon\.ico$', app.meta.favicon),
+                        url(r'^cstyle\.css$', app.meta.custom_css, name="custom_css"),
+
+                        url(r'^m/(?P<skin>\w+)/media/(?P<path>.*)$', app.meta.media , name='osqa_media'),
+                        url(r'^%s(?P<path>.*)$' % _('upfiles/'), 'django.views.static.serve',
+                            {'document_root': os.path.join(APP_PATH, 'upfiles').replace('\\', '/')},
+                            name='uploaded_file',
+                            ),
+
+                        url(r'^%s$' % _('faq/'), app.meta.static, {'content': settings.FAQ_PAGE_TEXT, 'title': _('FAQ')}
+                            , name='faq'),
+                        url(r'^%s$' % _('about/'), app.meta.static,
+                            {'content': settings.ABOUT_PAGE_TEXT, 'title': _('About')}, name='about'),
+                        url(r'^%s$' % _('markdown_help/'), app.meta.markdown_help, name='markdown_help'),
+                        url(r'^opensearch\.xml$', app.meta.opensearch, name='opensearch'),
+                        url(r'^opensearch\.xml$', app.meta.opensearch, name='opensearch'),
+                        url(r'^%s$' % _('privacy/'), app.meta.privacy, name='privacy'),
+                        url(r'^%s$' % _('logout/'), app.meta.logout, name='logout'),
+                        url(r'^%s(?P<id>\d+)/%s$' % (_('answers/'), _('edit/')), app.writers.edit_answer,
+                            name='edit_answer'),
+                        url(r'^%s(?P<id>\d+)/$' % _('revisions/'), app.readers.revisions, name='revisions'),
+                        url(r'^%s$' % _('questions/'), app.readers.questions, name='questions'),
+                        url(r'^%s%s$' % (_('questions/'), _('ask/')), app.writers.ask, name='ask'),
+                        url(r'^%s%s$' % (_('questions/'), _('related_questions/')), app.commands.related_questions,
+                            name='related_questions'),
+
+                        url(r'^%s%s$' % (_('questions/'), _('unanswered/')), app.readers.unanswered, name='unanswered'),
+                        url(r'^%s(?P<mode>[\w\-]+)/(?P<user>\d+)/(?P<slug>.*)/$' % _('questions/'), app.readers.user_questions, name="user_questions"),
+
+
+                        url(r'^%s(?P<id>\d+)/%s$' % (_('questions/'), _('edit/')), app.writers.edit_question,
+                            name='edit_question'),
+                        url(r'^%s(?P<id>\d+)/%s$' % (_('questions/'), _('close/')), app.commands.close,
+                            kwargs=dict(close=True), name='close'),
+                        url(r'^%s(?P<id>\d+)/%s$' % (_('questions/'), _('reopen/')), app.commands.close,
+                            kwargs=dict(close=False), name='reopen'),
+                        url(r'^%s(?P<id>\d+)/%s$' % (_('questions/'), _('answer/')), app.writers.answer, name='answer'),
+                        url(r'^%s(?P<action>\w+)/$' % _('pending-data/'), app.writers.manage_pending_data, name='manage_pending_data'),
+
+                        url(r'^%s(?P<id>\d+)/(?P<vote_type>[a-z]+)/' % _('vote/'), app.commands.vote_post,
+                            name='vote_post'),
+                        url(r'^%s(?P<id>\d+)/$' % _('like_comment/'), app.commands.like_comment, name="like_comment"),
+                        url(r'^%s(?P<id>\d+)/' % _('comment/'), app.commands.comment, name='comment'),
+                        url(r'^%s(?P<id>\d+)/$' % _('delete_comment/'), app.commands.delete_comment,
+                            name="delete_comment"),
+                        url(r'^%s(?P<id>\d+)/$' % _('convert_comment/'), app.commands.convert_comment_to_answer,
+                            name="convert_comment"),
+                        url(r'^%s(?P<id>\d+)/$' % _('accept_answer/'), app.commands.accept_answer, name="accept_answer")
+                        ,
+                        url(r'^%s(?P<id>\d+)/$' % _('mark_favorite/'), app.commands.mark_favorite, name="mark_favorite")
+                        ,
+                        url(r'^%s(?P<id>\d+)/' % _('flag/'), app.commands.flag_post, name='flag_post'),
+                        url(r'^%s(?P<id>\d+)/' % _('delete/'), app.commands.delete_post, name='delete_post'),
+                        url(r'^%s(?P<id>\d+)/(?P<user>\d+)?$' % _('subscribe/'), app.commands.subscribe, name="subscribe"),
+                        url(r'^%s(?P<id>\d+)/$' % _('subscribe/'), app.commands.subscribe, name="subscribe_simple"),
+                        url(r'^%s' % _('matching_tags/'), app.commands.matching_tags, name='matching_tags'),
+                        url(r'^%s' % _('matching_users/'), app.commands.matching_users, name='matching_users'),
+                        url(r'^%s(?P<id>\d+)/' % _('node_markdown/'), app.commands.node_markdown, name='node_markdown'),
+                        url(r'^%s(?P<id>\d+)/' % _('convert/'), app.commands.convert_to_comment,
+                            name='convert_to_comment'),
+                        url(r'^%s(?P<id>\d+)/' % _('convert_to_question/'), app.commands.convert_to_question,
+                            name='convert_to_question'),
+                        url(r'^%s(?P<id>\d+)/' % _('wikify/'), app.commands.wikify, name='wikify'),
+
+                        url(r'^%s(?P<id>\d+)/(?P<slug>[\w-]*)$' % _('question/'),
+                            'django.views.generic.simple.redirect_to', {'url': '/questions/%(id)s/%(slug)s'}),
+                        url(r'^%s(?P<id>\d+)/?$' % _('questions/'), app.readers.question, name='question'),
+                        url(r'^%s(?P<id>\d+)/(?P<slug>.*)/(?P<answer>\d+)$' % _('questions/'), app.readers.question),
+                        url(r'^%s(?P<id>\d+)/(?P<slug>.*)$' % _('questions/'), app.readers.question, name='question'),
+
+
+                        url(r'^%s$' % _('tags/'), app.readers.tags, name='tags'),
+                        url(r'^%s(?P<tag>.*)/$' % _('tags/'), app.readers.tag, name='tag_questions'),
+
+                        url(r'^%s%s(?P<tag>[^/]+)/$' % (_('mark-tag/'),_('interesting/')), app.commands.mark_tag, \
+                                kwargs={'reason':'good','action':'add'}, \
+                                name='mark_interesting_tag'),
+
+                        url(r'^%s%s(?P<tag>[^/]+)/$' % (_('mark-tag/'),_('ignored/')), app.commands.mark_tag, \
+                                kwargs={'reason':'bad','action':'add'}, \
+                                name='mark_ignored_tag'),
+
+                        url(r'^%s(?P<tag>[^/]+)/$' % _('unmark-tag/'), app.commands.mark_tag, \
+                                kwargs={'action':'remove'}, \
+                                name='mark_ignored_tag'),
+
+
+                        url(r'^%s$' % _('users/'), app.users.users, name='users'),
+                        # url(r'^%s$' % _('online_users/'), app.users.online_users, name='online_users'),
+
+
+                        url(r'^%s(?P<id>\d+)/%s$' % (_('users/'), _('edit/')), app.users.edit_user, name='edit_user'),
+                        url(r'^%s(?P<id>\d+)/%s$' % (_('users/'), _('award/')), app.users.award_points,
+                            name='user_award_points'),
+                        url(r'^%s(?P<id>\d+)/%s$' % (_('users/'), _('suspend/')), app.users.suspend, name='user_suspend'
+                            ),
+                        url(r'^%s(?P<id>\d+)/%s(?P<action>[a-z]+)/(?P<status>[a-z]+)/$' % (_('users/'), _('powers/')),
+                            app.users.user_powers, name='user_powers'),
+                        url(r'^%s(?P<id>\d+)/(?P<slug>.*)/%s$' % (_('users/'), _('subscriptions/')), app.users.user_subscriptions,
+                            name='user_subscriptions'),
+                        url(r'^%s(?P<id>\d+)/(?P<slug>.*)/%s$' % (_('users/'), _('preferences/')), app.users.user_preferences,
+                            name='user_preferences'),
+                        url(r'^%s(?P<id>\d+)/(?P<slug>.*)/%s$' % (_('users/'), _('favorites/')),
+                            app.users.user_favorites, name='user_favorites'),
+                        url(r'^%s(?P<id>\d+)/(?P<slug>.*)/%s$' % (_('users/'), _('reputation/')),
+                            app.users.user_reputation, name='user_reputation'),
+                        url(r'^%s(?P<id>\d+)/(?P<slug>.*)/%s$' % (_('users/'), _('votes/')), app.users.user_votes,
+                            name='user_votes'),
+                        url(r'^%s(?P<id>\d+)/(?P<slug>.*)/%s$' % (_('users/'), _('recent/')), app.users.user_recent,
+                            name='user_recent'),
+                        url(r'^%s(?P<id>\d+)/(?P<slug>.*)/$' % _('users/'), app.users.user_profile, name='user_profile'),
+                        url(r'^%s$' % _('badges/'), app.meta.badges, name='badges'),
+                        url(r'^%s(?P<id>\d+)/(?P<slug>[\w-]+)/?$' % _('badges/'), app.meta.badge, name='badge'),
+                        # (r'^admin/doc/' % _('admin/doc'), include('django.contrib.admindocs.urls')),
+
+                        url(r'^%s$' % _('upload/'), app.writers.upload, name='upload'),
+                        url(r'^%s$' % _('search/'), app.readers.search, name='search'),
+                        url(r'^%s$' % _('contact/'), app.meta.feedback, name='feedback'),
+
+                        (r'^i18n/', include('django.conf.urls.i18n')),
+
+                        url(r'^%s%s$' % (_('account/'), _('signin/')), app.auth.signin_page, name='auth_signin'),
+                        url(r'^%s%s$' % (_('account/'), _('signout/')), app.auth.signout, name='user_signout'),
+                        url(r'^%s(?P<provider>\w+)/%s$' % (_('account/'), _('signin/')),
+                            app.auth.prepare_provider_signin, name='auth_provider_signin'),
+                        url(r'^%s(?P<provider>\w+)/%s$' % (_('account/'), _('done/')), app.auth.process_provider_signin,
+                            name='auth_provider_done'),
+                        url(r'^%s%s$' % (_('account/'), _('register/')), app.auth.external_register,
+                            name='auth_external_register'),
+                        url(r'^%s%s(?P<user>\d+)/(?P<code>.+)/$' % (_('account/'), _('validate/')),
+                            app.auth.validate_email, name="auth_validate_email"),
+                        url(r'^%s%s$' % (_('account/'), _('tempsignin/')), app.auth.request_temp_login,
+                            name="auth_request_tempsignin"),
+                        url(r'^%s%s(?P<user>\d+)/(?P<code>.+)/$' % (_('account/'), _('tempsignin/')),
+                            app.auth.temp_signin, name="auth_tempsignin"),
+                        url(r'^%s(?P<id>\d+)/%s$' % (_('account/'), _('authsettings/')), app.auth.auth_settings,
+                            name='user_authsettings'),
+                        url(r'^%s%s(?P<id>\d+)/%s$' % (_('account/'), _('providers/'), _('remove/')),
+                            app.auth.remove_external_provider, name='user_remove_external_provider'),
+                        url(r'^%s%s%s$' % (_('account/'), _('providers/'), _('add/')), app.auth.signin_page,
+                            name='user_add_external_provider'),
+                        url(r'^%s%s$' %(_('account/'), _('send-validation/')), app.auth.send_validation_email, name="send_validation_email"),
+
+
+                        url(r'^%s$' % _('admin/'), app.admin.dashboard, name="admin_index"),
+                        url(r'^%s%s$' % (_('admin/'), _('switch_interface/')), app.admin.interface_switch,
+                            name="admin_switch_interface"),
+                        url(r'^%s%s$' % (_('admin/'), _('statistics/')), app.admin.statistics, name="admin_statistics"),
+                        url(r'^%s%s$' % (_('admin/'), _('denormalize/')), app.admin.recalculate_denormalized,
+                            name="admin_denormalize"),
+                        url(r'^%s%s$' % (_('admin/'), _('go_bootstrap/')), app.admin.go_bootstrap,
+                            name="admin_go_bootstrap"),
+                        url(r'^%s%s$' % (_('admin/'), _('go_defaults/')), app.admin.go_defaults,
+                            name="admin_go_defaults"),
+                        url(r'^%s%s(?P<set_name>\w+)/(?P<var_name>\w+)/$' % (_('admin/'), _('settings/')),
+                            app.admin.get_default, name="admin_default"),
+                        url(r'^%s%s$' % (_('admin/'), _('maintenance/')), app.admin.maintenance,
+                            name="admin_maintenance"),
+                        url(r'^%s%s$' % (_('admin/'), _('flagged_posts/')), app.admin.flagged_posts,
+                            name="admin_flagged_posts"),
+                        url(r'^%s%s$' % (_('admin/'), _('static_pages/')), app.admin.static_pages,
+                            name="admin_static_pages"),
+
+                        url(r'^%s%s%s$' % (_('admin/'), _('static_pages/'), _('new/')), app.admin.edit_page,
+                            name="admin_new_page"),
+                        url(r'^%s%s%s(?P<id>\d+)/$' % (_('admin/'), _('static_pages/'), _('edit/')), app.admin.edit_page
+                            , name="admin_edit_page"),
+
+                        url(r'^%s%s(?P<name>\w+)/$' % (_('admin/'), _('tools/')), app.admin.tools_page,
+                            name="admin_tools"),
+
+                        url(r'^%s%s(?P<set_name>\w+)/$' % (_('admin/'), _('settings/')), app.admin.settings_set,
+                            name="admin_set"),
+
+                        url(r'^feeds/rss[/]?$', app.readers.feed, name="latest_questions_feed"),
+
+                        url(r'^(?P<path>.+)$', app.meta.page, name="static_page"),
+                        )
diff --git a/forum/modules/template_loader.py/forum/user_messages/__init__.py b/forum/modules/template_loader.py/forum/user_messages/__init__.py
new file mode 100644 (file)
index 0000000..0136c88
--- /dev/null
@@ -0,0 +1,36 @@
+"""
+Lightweight session-based messaging system.
+
+Time-stamp: <2009-03-10 19:22:29 carljm __init__.py>
+
+"""
+VERSION = (0, 1, 'pre')
+
+def create_message (request, message):
+    """
+    Create a message in the current session.
+
+    """
+    assert hasattr(request, 'session'), "django-session-messages requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.sessions.middleware.SessionMiddleware'."
+    
+    try:
+        request.session['messages'].append(message)
+    except KeyError:
+        request.session['messages'] = [message]
+
+def get_and_delete_messages (request, include_auth=False):
+    """
+    Get and delete all messages for current session.
+
+    Optionally also fetches user messages from django.contrib.auth.
+
+    """
+    assert hasattr(request, 'session'), "django-session-messages requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.sessions.middleware.SessionMiddleware'."
+
+    messages = request.session.pop('messages', [])
+
+    if include_auth and request.user.is_authenticated():
+        messages.extend(request.user.get_and_delete_messages())
+    
+    return messages
+
diff --git a/forum/modules/template_loader.py/forum/user_messages/context_processors.py b/forum/modules/template_loader.py/forum/user_messages/context_processors.py
new file mode 100644 (file)
index 0000000..5f7b857
--- /dev/null
@@ -0,0 +1,55 @@
+"""
+Context processor for lightweight session messages.
+
+Time-stamp: <2008-07-19 23:16:19 carljm context_processors.py>
+
+"""
+from django.utils.encoding import StrAndUnicode
+
+from forum.user_messages import get_and_delete_messages
+
+def user_messages (request):
+    """
+    Returns session messages for the current session.
+
+    """
+    messages = request.user.get_and_delete_messages()
+    #if request.user.is_authenticated():
+    #else:
+    #    messages = LazyMessages(request)
+    #import inspect
+    #print inspect.stack()[1]
+    #print messages
+    return { 'user_messages': messages }
+
+class LazyMessages (StrAndUnicode):
+    """
+    Lazy message container, so messages aren't actually retrieved from
+    session and deleted until the template asks for them.
+
+    """
+    def __init__(self, request):
+        self.request = request
+
+    def __iter__(self):
+        return iter(self.messages)
+
+    def __len__(self):
+        return len(self.messages)
+
+    def __nonzero__(self):
+        return bool(self.messages)
+
+    def __unicode__(self):
+        return unicode(self.messages)
+
+    def __getitem__(self, *args, **kwargs):
+        return self.messages.__getitem__(*args, **kwargs)
+
+    def _get_messages(self):
+        if hasattr(self, '_messages'):
+            return self._messages
+        self._messages = get_and_delete_messages(self.request)
+        return self._messages
+    messages = property(_get_messages)
+    
diff --git a/forum/modules/template_loader.py/forum/utils/__init__.py b/forum/modules/template_loader.py/forum/utils/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/forum/modules/template_loader.py/forum/utils/decorators.py b/forum/modules/template_loader.py/forum/utils/decorators.py
new file mode 100644 (file)
index 0000000..e4e7acb
--- /dev/null
@@ -0,0 +1,25 @@
+from django.http import HttpResponse, HttpResponseForbidden, Http404
+from django.utils import simplejson
+
+def ajax_login_required(view_func):
+    def wrap(request,*args,**kwargs):
+        if request.user.is_authenticated():
+            return view_func(request,*args,**kwargs)
+        else:
+            json = simplejson.dumps({'login_required':True})
+            return HttpResponseForbidden(json,mimetype='application/json')
+    return wrap
+
+def ajax_method(view_func):
+    def wrap(request,*args,**kwargs):
+        if not request.is_ajax():
+            raise Http404
+        retval = view_func(request,*args,**kwargs)
+        if isinstance(retval, HttpResponse):
+            retval.mimetype = 'application/json'
+            return retval
+        else:
+            json = simplejson.dumps(retval)
+            return HttpResponse(json,mimetype='application/json')
+    return wrap
+            
diff --git a/forum/modules/template_loader.py/forum/utils/diff.py b/forum/modules/template_loader.py/forum/utils/diff.py
new file mode 100644 (file)
index 0000000..d741d78
--- /dev/null
@@ -0,0 +1,66 @@
+#!/usr/bin/python2.2
+"""HTML Diff: http://www.aaronsw.com/2002/diff
+Rough code, badly documented. Send me comments and patches."""
+
+__author__ = 'Aaron Swartz <me@aaronsw.com>'
+__copyright__ = '(C) 2003 Aaron Swartz. GNU GPL 2.'
+__version__ = '0.22'
+
+import difflib, string
+
+def isTag(x): return x[0] == "<" and x[-1] == ">"
+
+def textDiff(a, b):
+       """Takes in strings a and b and returns a human-readable HTML diff."""
+
+       out = []
+       a, b = html2list(a), html2list(b)
+       s = difflib.SequenceMatcher(None, a, b)
+       for e in s.get_opcodes():
+               if e[0] == "replace":
+                       # @@ need to do something more complicated here
+                       # call textDiff but not for html, but for some html... ugh
+                       # gonna cop-out for now
+                       out.append('<del>'+''.join(a[e[1]:e[2]]) + '</del><ins>'+''.join(b[e[3]:e[4]])+"</ins>")
+               elif e[0] == "delete":
+                       out.append('<del >'+ ''.join(a[e[1]:e[2]]) + "</del>")
+               elif e[0] == "insert":
+                       out.append('<ins >'+''.join(b[e[3]:e[4]]) + "</ins>")
+               elif e[0] == "equal":
+                       out.append(''.join(b[e[3]:e[4]]))
+               else: 
+                       raise "Um, something's broken. I didn't expect a '" + `e[0]` + "'."
+       return ''.join(out)
+
+def html2list(x, b=0):
+       mode = 'char'
+       cur = ''
+       out = []
+       for c in x:
+               if mode == 'tag':
+                       if c == '>': 
+                               if b: cur += ']'
+                               else: cur += c
+                               out.append(cur); cur = ''; mode = 'char'
+                       else: cur += c
+               elif mode == 'char':
+                       if c == '<': 
+                               out.append(cur)
+                               if b: cur = '['
+                               else: cur = c
+                               mode = 'tag'
+                       elif c in string.whitespace: out.append(cur+c); cur = ''
+                       else: cur += c
+       out.append(cur)
+       return filter(lambda x: x is not '', out)
+
+if __name__ == '__main__':
+       import sys
+       try:
+               a, b = sys.argv[1:3]
+       except ValueError:
+               print "htmldiff: highlight the differences between two html files"
+               print "usage: " + sys.argv[0] + " a b"
+               sys.exit(1)
+       print textDiff(open(a).read(), open(b).read())
+       
diff --git a/forum/modules/template_loader.py/forum/utils/djangofix.py b/forum/modules/template_loader.py/forum/utils/djangofix.py
new file mode 100644 (file)
index 0000000..d74e48d
--- /dev/null
@@ -0,0 +1,21 @@
+import re
+import urllib
+from forum.modules import decorate
+
+from django.template.defaultfilters import slugify
+from django.utils.safestring import mark_safe
+from django.utils.http import urlquote_plus
+
+slug_re = re.compile(r'\w+', re.UNICODE)
+
+@decorate(slugify)
+def imp_slugify(origin, value):
+    if settings.ALLOW_UNICODE_IN_SLUGS:
+        try:
+            bits = slug_re.findall(value.lower())
+            return mark_safe("-".join(bits))
+        except:
+            pass
+    return origin(value)
+
+from forum import settings
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum/utils/html.py b/forum/modules/template_loader.py/forum/utils/html.py
new file mode 100644 (file)
index 0000000..bf84e2f
--- /dev/null
@@ -0,0 +1,75 @@
+"""Utilities for working with HTML."""
+#import html5lib
+from html5lib import sanitizer, serializer, tokenizer, treebuilders, treewalkers, HTMLParser
+from django.utils.html import strip_tags
+from forum.utils.html2text import HTML2Text
+from django.template import mark_safe
+from forum import settings
+
+class HTMLSanitizerMixin(sanitizer.HTMLSanitizerMixin):
+    acceptable_elements = ('a', 'abbr', 'acronym', 'address', 'b', 'big',
+        'blockquote', 'br', 'caption', 'center', 'cite', 'code', 'col',
+        'colgroup', 'dd', 'del', 'dfn', 'dir', 'div', 'dl', 'dt', 'em', 'font',
+        'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'ins', 'kbd',
+        'li', 'ol', 'p', 'pre', 'q', 's', 'samp', 'small', 'span', 'strike',
+        'strong', 'sub', 'sup', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead',
+        'tr', 'tt', 'u', 'ul', 'var')
+
+    acceptable_attributes = ('abbr', 'align', 'alt', 'axis', 'border',
+        'cellpadding', 'cellspacing', 'char', 'charoff', 'charset', 'cite',
+        'cols', 'colspan', 'datetime', 'dir', 'frame', 'headers', 'height',
+        'href', 'hreflang', 'hspace', 'lang', 'longdesc', 'name', 'nohref',
+        'noshade', 'nowrap', 'rel', 'rev', 'rows', 'rowspan', 'rules', 'scope',
+        'span', 'src', 'start', 'summary', 'title', 'type', 'valign', 'vspace',
+        'width')
+
+    allowed_elements = acceptable_elements
+    allowed_attributes = acceptable_attributes
+    allowed_css_properties = ()
+    allowed_css_keywords = ()
+    allowed_svg_properties = ()
+
+class HTMLSanitizer(tokenizer.HTMLTokenizer, HTMLSanitizerMixin):
+
+    def __iter__(self):
+        for token in tokenizer.HTMLTokenizer.__iter__(self):
+            token = self.sanitize_token(token)
+            if token:
+                yield token
+
+def sanitize_html(html):
+    """Sanitizes an HTML fragment."""
+    p = HTMLParser(tokenizer=HTMLSanitizer,
+                            tree=treebuilders.getTreeBuilder("dom"))
+    dom_tree = p.parseFragment(html)
+    walker = treewalkers.getTreeWalker("dom")
+    stream = walker(dom_tree)
+    s = serializer.HTMLSerializer(omit_optional_tags=False,
+                                  quote_attr_values=True)
+    output_generator = s.serialize(stream)
+    return u''.join(output_generator)
+
+def cleanup_urls(url):
+    return strip_tags(url)
+
+
+def html2text(s, ignore_tags=(), indent_width=4, page_width=80):
+    ignore_tags = [t.lower() for t in ignore_tags]
+    parser = HTML2Text(ignore_tags, indent_width, page_width)
+    parser.feed(s)
+    parser.close()
+    parser.generate()
+    return mark_safe(parser.result)
+
+def buildtag(name, content, **attrs):
+    return mark_safe('<%s %s>%s</%s>' % (name, " ".join('%s="%s"' % i for i in attrs.items()), unicode(content), name))
+
+def hyperlink(url, title, **attrs):
+    return mark_safe('<a href="%s" %s>%s</a>' % (url, " ".join('%s="%s"' % i for i in attrs.items()), title))
+
+def objlink(obj, **attrs):
+    return hyperlink(settings.APP_BASE_URL + obj.get_absolute_url(), unicode(obj), **attrs)
+
+    
+
+
diff --git a/forum/modules/template_loader.py/forum/utils/html2text.py b/forum/modules/template_loader.py/forum/utils/html2text.py
new file mode 100644 (file)
index 0000000..3b51771
--- /dev/null
@@ -0,0 +1,140 @@
+# Copyright (c) 2001 Chris Withers\r
+#\r
+# This Software is released under the MIT License:\r
+# http://www.opensource.org/licenses/mit-license.html\r
+# See license.txt for more details.\r
+#\r
+# $Id: html2text.py,v 1.7 2002/12/17 16:56:17 fresh Exp $\r
+\r
+import sgmllib\r
+from string import lower, replace, split, join\r
+\r
+class HTML2Text(sgmllib.SGMLParser):\r
+\r
+    from htmlentitydefs import entitydefs # replace entitydefs from sgmllib\r
+\r
+    def __init__(self, ignore_tags=(), indent_width=4, page_width=80):\r
+        sgmllib.SGMLParser.__init__(self)\r
+        self.result = ""\r
+        self.indent = 0\r
+        self.ol_number = 0\r
+        self.page_width=page_width\r
+        self.inde_width=indent_width\r
+        self.lines=[]\r
+        self.line=[]\r
+        self.ignore_tags = ignore_tags\r
+\r
+    def add_text(self,text):\r
+        # convert text into words\r
+        words = split(replace(text,'\n',' '))\r
+        self.line.extend(words)\r
+\r
+    def add_break(self):\r
+        self.lines.append((self.indent,self.line))\r
+        self.line=[]\r
+\r
+    def generate(self):\r
+        # join lines with indents\r
+        indent_width = self.inde_width\r
+        page_width = self.page_width\r
+        out_paras=[]\r
+        for indent,line in self.lines+[(self.indent,self.line)]:\r
+\r
+            i=indent*indent_width\r
+            indent_string = i*' '\r
+            line_width = page_width-i\r
+\r
+            out_para=''\r
+            out_line=[]\r
+            len_out_line=0\r
+            for word in line:\r
+                len_word = len(word)\r
+                if len_out_line+len_word<line_width:\r
+                    out_line.append(word)\r
+                    len_out_line = len_out_line + len_word\r
+                else:\r
+                    out_para = out_para + indent_string + join(out_line, ' ') + '\n'\r
+                    out_line=[word]\r
+                    len_out_line=len_word\r
+\r
+            out_para = out_para + indent_string + join(out_line, ' ')\r
+            out_paras.append(out_para)\r
+\r
+        self.result = join(out_paras,'\n\n')\r
+\r
+\r
+    def mod_indent(self,i):\r
+        self.indent = self.indent + i\r
+        if self.indent < 0:\r
+            self.indent = 0\r
+\r
+    def handle_data(self, data):\r
+        if data:\r
+            self.add_text(data)\r
+\r
+    def unknown_starttag(self, tag, attrs):\r
+        """ Convert HTML to something meaningful in plain text """\r
+        tag = lower(tag)\r
+\r
+        if tag not in self.ignore_tags:\r
+            if tag[0]=='h' or tag in ['br','pre','p','hr']:\r
+                # insert a blank line\r
+                self.add_break()\r
+\r
+            elif tag =='img':\r
+                # newline, text, newline\r
+                src = ''\r
+\r
+                for k, v in attrs:\r
+                    if lower(k) == 'src':\r
+                        src = v\r
+\r
+                self.add_break()\r
+                self.add_text('Image: ' + src)\r
+\r
+            elif tag =='li':\r
+                self.add_break()\r
+                if self.ol_number:\r
+                    # num - text\r
+                    self.add_text(str(self.ol_number) + ' - ')\r
+                    self.ol_number = self.ol_number + 1\r
+                else:\r
+                    # - text\r
+                    self.add_text('- ')\r
+\r
+            elif tag in ['dd','dt']:\r
+                self.add_break()\r
+                # increase indent\r
+                self.mod_indent(+1)\r
+\r
+            elif tag in ['ul','dl','ol']:\r
+                # blank line\r
+                # increase indent\r
+                self.mod_indent(+1)\r
+                if tag=='ol':\r
+                    self.ol_number = 1\r
+\r
+    def unknown_endtag(self, tag):\r
+        """ Convert HTML to something meaningful in plain text """\r
+        tag = lower(tag)\r
+\r
+        if tag not in self.ignore_tags:\r
+            if tag[0]=='h' or tag in ['pre']:\r
+                # newline, text, newline\r
+                self.add_break()\r
+\r
+            elif tag =='li':\r
+                self.add_break()\r
+\r
+            elif tag in ['dd','dt']:\r
+                self.add_break()\r
+                # descrease indent\r
+                self.mod_indent(-1)\r
+\r
+            elif tag in ['ul','dl','ol']:\r
+                # blank line\r
+                self.add_break()\r
+                # decrease indent\r
+                self.mod_indent(-1)\r
+                self.ol_number = 0\r
+\r
diff --git a/forum/modules/template_loader.py/forum/utils/lists.py b/forum/modules/template_loader.py/forum/utils/lists.py
new file mode 100644 (file)
index 0000000..bbcfae9
--- /dev/null
@@ -0,0 +1,86 @@
+"""Utilities for working with lists and sequences."""
+
+def flatten(x):
+    """
+    Returns a single, flat list which contains all elements retrieved
+    from the sequence and all recursively contained sub-sequences
+    (iterables).
+
+    Examples:
+    >>> [1, 2, [3, 4], (5, 6)]
+    [1, 2, [3, 4], (5, 6)]
+
+    From http://kogs-www.informatik.uni-hamburg.de/~meine/python_tricks
+    """
+    result = []
+    for el in x:
+        if hasattr(el, '__iter__') and not isinstance(el, basestring):
+            result.extend(flatten(el))
+        else:
+            result.append(el)
+    return result
+
+def batch_size(items, size):
+    """
+    Retrieves items in batches of the given size.
+
+    >>> l = range(1, 11)
+    >>> batch_size(l, 3)
+    [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
+    >>> batch_size(l, 5)
+    [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]
+    """
+    return [items[i:i+size] for i in xrange(0, len(items), size)]
+
+def batches(items, number):
+    """
+    Retrieves items in the given number of batches.
+
+    >>> l = range(1, 11)
+    >>> batches(l, 1)
+    [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]
+    >>> batches(l, 2)
+    [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]
+    >>> batches(l, 3)
+    [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]]
+    >>> batches(l, 4)
+    [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
+    >>> batches(l, 5)
+    [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
+
+    Initial batches will contain as many items as possible in cases where
+    there are not enough items to be distributed evenly.
+
+    >>> batches(l, 6)
+    [[1, 2], [3, 4], [5, 6], [7, 8], [9], [10]]
+    >>> batches(l, 7)
+    [[1, 2], [3, 4], [5, 6], [7], [8], [9], [10]]
+    >>> batches(l, 8)
+    [[1, 2], [3, 4], [5], [6], [7], [8], [9], [10]]
+    >>> batches(l, 9)
+    [[1, 2], [3], [4], [5], [6], [7], [8], [9], [10]]
+    >>> batches(l, 10)
+    [[1], [2], [3], [4], [5], [6], [7], [8], [9], [10]]
+
+    If there are more batches than items, empty batches will be appended
+    to the batch list.
+
+    >>> batches(l, 11)
+    [[1], [2], [3], [4], [5], [6], [7], [8], [9], [10], []]
+    >>> batches(l, 12)
+    [[1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [], []]
+    """
+    div, mod= divmod(len(items), number)
+    if div > 1:
+        if mod:
+            div += 1
+        return batch_size(items, div)
+    else:
+        if not div:
+            return [[item] for item in items] + [[]] * (number - mod)
+        elif div == 1 and not mod:
+            return [[item] for item in items]
+        else:
+            # mod now tells you how many lists of 2 you can fit in
+            return ([items[i*2:(i*2)+2] for i in xrange(0, mod)] +
+                    [[item] for item in items[mod*2:]])
diff --git a/forum/modules/template_loader.py/forum/utils/mail.py b/forum/modules/template_loader.py/forum/utils/mail.py
new file mode 100644 (file)
index 0000000..7a61292
--- /dev/null
@@ -0,0 +1,88 @@
+import email
+import socket
+import os
+
+try:
+    from email.mime.multipart import MIMEMultipart
+    from email.mime.text import MIMEText
+    from email.mime.image import MIMEImage
+    from email.header import Header
+except:
+    from email.MIMEMultipart import MIMEMultipart
+    from email.MIMEText import MIMEText
+    from email.MIMEImage import MIMEImage
+    from email.Header import Header
+
+from django.core.mail import DNS_NAME
+from smtplib import SMTP
+from forum import settings
+from django.template import loader, Context, Template
+from forum.utils.html import sanitize_html
+from forum.context import application_settings
+from forum.utils.html2text import HTML2Text
+from threading import Thread
+
+def send_template_email(recipients, template, context):
+    t = loader.get_template(template)
+    context.update(dict(recipients=recipients, settings=settings))
+    t.render(Context(context))
+
+def create_and_send_mail_messages(messages):
+    if not settings.EMAIL_HOST:
+        return
+
+    sender = Header(unicode(settings.APP_SHORT_NAME), 'utf-8')
+    sender.append('<%s>' % unicode(settings.DEFAULT_FROM_EMAIL))
+    sender = u'%s <%s>' % (unicode(settings.APP_SHORT_NAME), unicode(settings.DEFAULT_FROM_EMAIL))
+
+    try:
+        connection = SMTP(str(settings.EMAIL_HOST), str(settings.EMAIL_PORT),
+                          local_hostname=DNS_NAME.get_fqdn())
+
+        if (bool(settings.EMAIL_USE_TLS)):
+            connection.ehlo()
+            connection.starttls()
+            connection.ehlo()
+
+        if settings.EMAIL_HOST_USER and settings.EMAIL_HOST_PASSWORD:
+            connection.login(str(settings.EMAIL_HOST_USER), str(settings.EMAIL_HOST_PASSWORD))
+
+        if sender is None:
+            sender = str(settings.DEFAULT_FROM_EMAIL)
+
+        for recipient, subject, html, text, media in messages:
+            msgRoot = MIMEMultipart('related')
+
+            msgRoot['Subject'] = Header(subject, 'utf-8')
+            msgRoot['From'] = sender
+
+            to = Header(recipient.username, 'utf-8')
+            to.append('<%s>' % recipient.email)
+            msgRoot['To'] = to
+
+            msgRoot.preamble = 'This is a multi-part message from %s.' % unicode(settings.APP_SHORT_NAME).encode('utf8')
+
+            msgAlternative = MIMEMultipart('alternative')
+            msgRoot.attach(msgAlternative)
+
+            msgAlternative.attach(MIMEText(text.encode('utf-8'), _charset='utf-8'))
+            msgAlternative.attach(MIMEText(html.encode('utf-8'), 'html', _charset='utf-8'))
+
+            for alias, location in media.items():
+                fp = open(location, 'rb')
+                msgImage = MIMEImage(fp.read())
+                fp.close()
+                msgImage.add_header('Content-ID', '<'+alias+'>')
+                msgRoot.attach(msgImage)
+
+            try:
+                connection.sendmail(sender, [recipient.email], msgRoot.as_string())
+            except Exception, e:
+                pass
+
+        try:
+            connection.quit()
+        except socket.sslerror:
+            connection.close()
+    except Exception, e:
+        pass
diff --git a/forum/modules/template_loader.py/forum/utils/pagination.py b/forum/modules/template_loader.py/forum/utils/pagination.py
new file mode 100644 (file)
index 0000000..1d36b42
--- /dev/null
@@ -0,0 +1,313 @@
+import math
+from django.utils.datastructures import SortedDict
+from django import template
+from django.core.paginator import Paginator, EmptyPage
+from django.utils.translation import ugettext as _
+from django.http import Http404
+from django.utils.http import urlquote
+from django.utils.safestring import mark_safe
+from django.utils.html import strip_tags, escape
+from forum.utils.html import sanitize_html
+import logging
+
+def generate_uri(querydict, exclude=None):
+    all = []
+
+    for k, l in querydict.iterlists():
+        if (not exclude) or (not k in exclude):
+            all += ["%s=%s" % (k, urlquote(strip_tags(v))) for v in l]
+        
+    return "&".join(all)
+
+class SortBase(object):
+    def __init__(self, label, description=''):
+        self.label = label
+        self.description = description
+
+class SimpleSort(SortBase):
+    def __init__(self, label, order_by, description=''):
+        super(SimpleSort, self) .__init__(label, description)
+        self.order_by = order_by
+
+    def _get_order_by(self):
+        return isinstance(self.order_by, (list, tuple)) and self.order_by or [self.order_by]
+
+    def apply(self, objects):
+        return objects.order_by(*self._get_order_by())
+
+class PaginatorContext(object):
+    visible_page_range = 5
+    outside_page_range = 1
+
+    base_path = None
+
+    def __init__(self, id, sort_methods=None, default_sort=None, force_sort = None,
+                 pagesizes=None, default_pagesize=None, prefix=''):
+        self.id = id
+        if sort_methods:
+            self.has_sort = True
+            self.sort_methods = SortedDict(data=sort_methods)
+
+            if not default_sort:
+                default_sort = sort_methods[0][0]
+
+            self.default_sort = default_sort
+        else:
+            self.has_sort = False
+
+
+        if pagesizes:
+            self.has_pagesize = True
+            self.pagesizes = pagesizes
+
+            if not default_pagesize:
+                self.default_pagesize = pagesizes[int(math.ceil(float(len(pagesizes)) / 2)) - 1]
+            else:
+                self.default_pagesize = default_pagesize
+        else:
+            self.has_pagesize = False
+
+        self.force_sort = force_sort
+        self.prefix = prefix
+
+    def preferences(self, request):
+        if request.user.is_authenticated():
+            if request.user.prop.pagination:
+                preferences = request.user.prop.pagination.get(self.id, {})
+            else:
+                preferences = {}
+        else:
+            preferences = request.session.get('paginator_%s%s' % (self.prefix, self.id), {})
+
+        return preferences
+
+    def set_preferences(self, request, preferences):
+        if request.user.is_authenticated():
+            all_preferences = request.user.prop.pagination or {}
+            all_preferences[self.id] = preferences
+            request.user.prop.pagination = all_preferences
+        else:
+            request.session['paginator_%s%s' % (self.prefix, self.id)] = preferences
+
+    def pagesize(self, request, session_prefs=None):
+        if not session_prefs:
+            session_prefs = self.preferences(request)
+
+
+        if self.has_pagesize:
+            if request.GET.get(self.PAGESIZE, None):
+                try:
+                    pagesize = int(request.GET[self.PAGESIZE])
+                except ValueError:
+                    logging.error('Found invalid page size "%s", loading %s, refered by %s' % (
+                        request.GET.get(self.PAGESIZE, ''), request.path, request.META.get('HTTP_REFERER', 'UNKNOWN')
+                    ))
+                    raise Http404()
+
+                session_prefs[self.PAGESIZE] = pagesize
+            else:
+                pagesize = session_prefs.get(self.PAGESIZE, self.default_pagesize)
+
+            if not pagesize in self.pagesizes:
+                pagesize = self.default_pagesize
+        else:
+            pagesize = 30
+
+        return pagesize
+
+    def page(self, request):
+        try:
+            return int(request.GET.get(self.PAGE, "1").strip())
+        except ValueError:
+            logging.error('Found invalid page number "%s", loading %s, refered by %s' % (
+                request.GET.get(self.PAGE, ''), request.path, request.META.get('HTTP_REFERER', 'UNKNOWN')
+            ))
+            raise Http404()
+
+    def sort(self, request, session_prefs=None):
+        if not session_prefs:
+            session_prefs = self.preferences(request)
+
+        sort = None
+        sticky = request.user.is_authenticated() and request.user.prop.preferences and request.user.prop.preferences.get('sticky_sorts', False)
+
+        if self.has_sort:
+            if request.GET.get(self.SORT, None):
+                sort = request.GET[self.SORT]
+
+                if sticky:
+                    session_prefs[self.SORT] = sort
+            else:
+                sort = self.force_sort or (sticky and session_prefs.get(self.SORT, None)) or self.default_sort
+
+            if not sort in self.sort_methods:
+                sort = self.default_sort
+
+        return sort
+
+    def sorted(self, objects, request, session_prefs=None):
+        sort = self.sort(request, session_prefs)
+
+        if sort:
+            objects = self.sort_methods[sort].apply(objects)
+
+        return sort, objects
+
+    @property
+    def PAGESIZE(self):
+        return self.prefix and "%s_%s" % (self.prefix, _('pagesize')) or _('pagesize')
+
+    @property
+    def PAGE(self):
+        return self.prefix and "%s_%s" % (self.prefix, _('page')) or _('page')
+
+    @property
+    def SORT(self):
+        return self.prefix and "%s_%s" % (self.prefix, _('sort')) or _('sort')
+
+page_numbers_template = template.loader.get_template('paginator/page_numbers.html')
+page_sizes_template = template.loader.get_template('paginator/page_sizes.html')
+sort_tabs_template = template.loader.get_template('paginator/sort_tabs.html')
+
+def paginated(request, paginators, tpl_context):
+    if len(paginators) == 2 and isinstance(paginators[0], basestring):
+        paginators = (paginators,)
+
+    for list_name, context in paginators:
+        tpl_context[list_name] = _paginated(request, tpl_context[list_name], context)
+
+    return tpl_context
+
+def _paginated(request, objects, context):
+    session_prefs = context.preferences(request)
+
+    pagesize = context.pagesize(request, session_prefs)
+    page = context.page(request)
+    sort, objects = context.sorted(objects, request, session_prefs)
+
+    paginator = Paginator(objects, pagesize)
+
+    try:
+        page_obj = paginator.page(page)
+    except EmptyPage:
+        logging.error('Found invalid page number "%s", loading %s, refered by %s' % (
+            request.GET.get(context.PAGE, ''), request.path, request.META.get('HTTP_REFERER', 'UNKNOWN')
+        ))
+        raise Http404()
+
+    if context.base_path:
+        base_path = context.base_path
+    else:
+        base_path = request.path
+        get_params = generate_uri(request.GET, (context.PAGE, context.PAGESIZE, context.SORT))
+
+        if get_params:
+            base_path += "?" + get_params
+
+    url_joiner = "?" in base_path and "&" or "?"
+
+
+    def get_page():
+        object_list = page_obj.object_list
+
+        if hasattr(object_list, 'lazy'):
+            return object_list.lazy()
+        return object_list
+    paginator.page = get_page()
+
+    total_pages = paginator.num_pages
+
+    if total_pages > 1:
+        def page_nums():
+            total_pages = paginator.num_pages
+
+            has_previous = page > 1
+            has_next = page < total_pages
+
+            range_start = page - context.visible_page_range / 2
+            range_end = page + context.visible_page_range / 2
+
+            if range_start < 1:
+                range_end = context.visible_page_range
+                range_start = 1
+
+            if range_end > total_pages:
+                range_start = total_pages - context.visible_page_range + 1
+                range_end = total_pages
+                if range_start < 1:
+                    range_start = 1
+
+            page_numbers = []
+
+            if sort:
+                url_builder = lambda n: mark_safe("%s%s%s=%s&%s=%s" % (base_path, url_joiner, context.SORT, sort, context.PAGE, n))
+            else:
+                url_builder = lambda n: mark_safe("%s%s%s=%s" % (base_path, url_joiner, context.PAGE, n))
+
+            if range_start > (context.outside_page_range + 1):
+                page_numbers.append([(n, url_builder(n)) for n in range(1, context.outside_page_range + 1)])
+                page_numbers.append(None)
+            elif range_start > 1:
+                page_numbers.append([(n, url_builder(n)) for n in range(1, range_start)])
+
+            page_numbers.append([(n, url_builder(n)) for n in range(range_start, range_end + 1)])
+
+            if range_end < (total_pages - context.outside_page_range):
+                page_numbers.append(None)
+                page_numbers.append([(n, url_builder(n)) for n in range(total_pages - context.outside_page_range + 1, total_pages + 1)])
+            elif range_end < total_pages:
+                page_numbers.append([(n, url_builder(n)) for n in range(range_end + 1, total_pages + 1)])
+
+            return page_numbers_template.render(template.Context({
+                'has_previous': has_previous,
+                'previous_url': has_previous and url_builder(page - 1) or None,
+                'has_next': has_next,
+                'next_url': has_next and url_builder(page + 1) or None,
+                'current': page,
+                'page_numbers': page_numbers
+            }))
+        paginator.page_numbers = page_nums
+    else:
+        paginator.page_numbers = ''
+
+    if pagesize:
+        def page_sizes():
+            if sort:
+                url_builder = lambda s: mark_safe("%s%s%s=%s&%s=%s" % (escape(base_path), url_joiner, context.SORT, sort, context.PAGESIZE, s))
+            else:
+                url_builder = lambda s: mark_safe("%s%s%s=%s" % (escape(base_path), url_joiner, context.PAGESIZE, s))
+
+            sizes = [(s, url_builder(s)) for s in context.pagesizes]
+
+            return page_sizes_template.render(template.Context({
+                'current': pagesize,
+                'sizes': sizes
+            }))
+
+        paginator.page_sizes = page_sizes
+    else:
+        paginator.page_sizes = ''
+
+    if sort:
+        def sort_tabs():
+            url_builder = lambda s: mark_safe("%s%s%s=%s" % (escape(base_path), url_joiner, context.SORT, s))
+            sorts = [(n, s.label, url_builder(n), strip_tags(s.description)) for n, s in context.sort_methods.items()]
+
+            for name, label, url, descr in sorts:
+                paginator.__dict__['%s_sort_link' % name] = url
+
+            return sort_tabs_template.render(template.Context({
+                'current': sort,
+                'sorts': sorts,
+                'sticky': session_prefs.get('sticky_sort', False)
+            }))
+        paginator.sort_tabs = sort_tabs()
+        paginator.sort_description = mark_safe(context.sort_methods[sort].description)
+        paginator.current_sort = sort
+    else:
+        paginator.sort_tabs = paginator.sort_description = ''
+        paginator.current_sort = ''
+
+    context.set_preferences(request, session_prefs)
+    objects.paginator = paginator
+    return objects
diff --git a/forum/modules/template_loader.py/forum/utils/time.py b/forum/modules/template_loader.py/forum/utils/time.py
new file mode 100644 (file)
index 0000000..39e01d0
--- /dev/null
@@ -0,0 +1,4 @@
+import datetime
+
+def one_day_from_now():
+    return datetime.datetime.now() + datetime.timedelta(days=1)
diff --git a/forum/modules/template_loader.py/forum/utils/userlinking.py b/forum/modules/template_loader.py/forum/utils/userlinking.py
new file mode 100644 (file)
index 0000000..da476ee
--- /dev/null
@@ -0,0 +1,90 @@
+import re
+
+from forum.models import User,  Question,  Answer,  Comment
+
+def find_best_match_in_name(content,  uname,  fullname,  start_index):      
+    end_index = start_index + len(fullname)    
+    
+    while end_index > start_index:
+        if content[start_index : end_index].lower() == fullname.lower():
+            return content[start_index : end_index]
+            
+        while len(fullname) and fullname[-1] != ' ':
+            fullname = fullname[:-1]
+            
+        fullname = fullname.rstrip()
+        end_index = start_index + len(fullname)
+            
+    return uname    
+
+APPEAL_PATTERN = re.compile(r'(?<!\w)@\w+')
+
+def auto_user_link(node, content):
+    
+    # We should find the root of the node tree (question) the current node belongs to.
+    if isinstance(node,  Question):
+        question = node
+    elif isinstance(node,  Answer):
+        question = node.question
+    elif isinstance(node,  Comment):
+        if node.question:
+            question = node.question
+        elif node.answer:
+            question = node.answer.question
+    
+    # Now we've got the root question. Let's get the list of active users.
+    active_users = question.get_active_users()
+    
+    appeals = APPEAL_PATTERN.finditer(content)
+
+    replacements = []
+
+    for appeal in appeals:
+        # Try to find the profile URL
+        username = appeal.group(0)[1:]
+        
+        matches = []
+        
+        for user in active_users:
+            if user.username.lower().startswith(username.lower()):
+                matches.append(user)
+                
+        if len(matches) == 1:
+            replacements.append(
+                                (find_best_match_in_name(content,  username,  matches[0].username,  appeal.start(0) + 1),  matches[0])
+                                )                                
+        elif len(matches) == 0:
+            matches = User.objects.filter(username__istartswith=username)
+            
+        if (len(matches) == 0):
+                continue
+        
+        best_user_match = None
+        final_match = ""
+        
+        for user in matches:
+            user_match = find_best_match_in_name(content,  username,  user.username,  appeal.start(0) + 1)
+            
+            if (len(user_match) < len(final_match)): 
+                continue
+                
+            if (len(user_match) == len(final_match)):
+                if not (user.username.lower() == user_match.lower()):
+                    continue
+                    
+                if (best_user_match and (best_user_match.username == final_match)):
+                    continue
+                    
+            best_user_match = user
+            final_match = user_match
+        
+        replacements.append((final_match,  best_user_match))            
+    
+    for replacement in replacements:
+        to_replace = "@" + replacement[0]
+        profile_url = replacement[1].get_absolute_url()
+        
+        auto_link = '<a href="%s">%s</a>' % (profile_url, to_replace)
+        content = content.replace(to_replace, auto_link)        
+    
+    return content
diff --git a/forum/modules/template_loader.py/forum/views/__init__.py b/forum/modules/template_loader.py/forum/views/__init__.py
new file mode 100644 (file)
index 0000000..f169b50
--- /dev/null
@@ -0,0 +1,17 @@
+import readers
+import writers
+import commands
+import users
+import meta
+import auth
+import admin
+
+#from forum.modules.decorators import decorate_all
+
+#decorate_all(readers)
+#decorate_all(writers)
+#decorate_all(commands)
+#decorate_all(users)
+#decorate_all(meta)
+#decorate_all(auth)
+#decorate_all(admin)
diff --git a/forum/modules/template_loader.py/forum/views/admin.py b/forum/modules/template_loader.py/forum/views/admin.py
new file mode 100644 (file)
index 0000000..40a098a
--- /dev/null
@@ -0,0 +1,554 @@
+from datetime import datetime, timedelta
+import os, time, csv, random
+
+from django.shortcuts import render_to_response, get_object_or_404
+from django.core.urlresolvers import reverse
+from django.http import HttpResponseRedirect, HttpResponse, Http404
+from forum.http_responses import HttpResponseUnauthorized
+from django.template import RequestContext
+from django.utils.translation import ugettext as _
+from django.utils import simplejson
+from django.db import models
+from forum.settings.base import Setting
+from forum.forms import MaintenanceModeForm, PageForm, CreateUserForm
+from forum.settings.forms import SettingsSetForm
+from forum.utils import pagination, html
+
+from forum.models import Question, Answer, User, Node, Action, Page, NodeState, Tag
+from forum.models.node import NodeMetaClass
+from forum.actions import NewPageAction, EditPageAction, PublishAction, DeleteAction, UserJoinsAction, CloseAction
+from forum import settings
+
+TOOLS = {}
+
+def super_user_required(fn):
+    def wrapper(request, *args, **kwargs):
+        if request.user.is_authenticated() and request.user.is_superuser:
+            return fn(request, *args, **kwargs)
+        else:
+            return HttpResponseUnauthorized(request)
+
+    return wrapper
+
+def admin_page(fn):
+    @super_user_required
+    def wrapper(request, *args, **kwargs):
+        res = fn(request, *args, **kwargs)
+        if isinstance(res, HttpResponse):
+            return res
+
+        template, context = res
+        context['basetemplate'] = settings.DJSTYLE_ADMIN_INTERFACE and "osqaadmin/djstyle_base.html" or "osqaadmin/base.html"
+        context['allsets'] = Setting.sets
+        context['othersets'] = sorted(
+                [s for s in Setting.sets.values() if not s.name in
+                ('basic', 'users', 'email', 'paths', 'extkeys', 'repgain', 'minrep', 'voting', 'accept', 'badges', 'about', 'faq', 'sidebar',
+                'form', 'moderation', 'css', 'headandfoot', 'head', 'view', 'urls')]
+                , lambda s1, s2: s1.weight - s2.weight)
+
+        context['tools'] = TOOLS
+
+        unsaved = request.session.get('previewing_settings', {})
+        context['unsaved'] = set([getattr(settings, s).set.name for s in unsaved.keys() if hasattr(settings, s)])
+
+        return render_to_response(template, context, context_instance=RequestContext(request))
+
+    return wrapper
+
+def admin_tools_page(name, label):    
+    def decorator(fn):
+        fn = admin_page(fn)
+        fn.label = label
+        TOOLS[name] = fn
+
+        return fn
+    return decorator
+
+class ActivityPaginatorContext(pagination.PaginatorContext):
+    def __init__(self):
+        super (ActivityPaginatorContext, self).__init__('ADMIN_RECENT_ACTIVITY', pagesizes=(20, 40, 80), default_pagesize=40)
+
+@admin_page
+def dashboard(request):
+    return ('osqaadmin/dashboard.html', pagination.paginated(request, ("recent_activity", ActivityPaginatorContext()), {
+    'settings_pack': unicode(settings.SETTINGS_PACK),
+    'statistics': get_statistics(),
+    'recent_activity': get_recent_activity(),
+    'flagged_posts': get_flagged_posts(),
+    }))
+
+@super_user_required
+def interface_switch(request):
+    if request.GET and request.GET.get('to', None) and request.GET['to'] in ('default', 'djstyle'):
+        settings.DJSTYLE_ADMIN_INTERFACE.set_value(request.GET['to'] == 'djstyle')
+
+    return HttpResponseRedirect(reverse('admin_index'))
+
+@admin_page
+def statistics(request):
+    today = datetime.now()
+    last_month = today - timedelta(days=30)
+
+    last_month_questions = Question.objects.filter_state(deleted=False).filter(added_at__gt=last_month
+                                                                               ).order_by('added_at').values_list(
+            'added_at', flat=True)
+
+    last_month_n_questions = Question.objects.filter_state(deleted=False).filter(added_at__lt=last_month).count()
+    qgraph_data = simplejson.dumps([
+    (time.mktime(d.timetuple()) * 1000, i + last_month_n_questions)
+    for i, d in enumerate(last_month_questions)
+    ])
+
+    last_month_users = User.objects.filter(date_joined__gt=last_month
+                                           ).order_by('date_joined').values_list('date_joined', flat=True)
+
+    last_month_n_users = User.objects.filter(date_joined__lt=last_month).count()
+
+    ugraph_data = simplejson.dumps([
+    (time.mktime(d.timetuple()) * 1000, i + last_month_n_users)
+    for i, d in enumerate(last_month_users)
+    ])
+
+    return 'osqaadmin/statistics.html', {
+    'graphs': [
+            {
+            'id': 'questions_graph',
+            'caption': _("Questions Graph"),
+            'data': qgraph_data
+            }, {
+            'id': 'userss_graph',
+            'caption': _("Users Graph"),
+            'data': ugraph_data
+            }
+            ]
+    }
+
+@admin_page
+def tools_page(request, name):
+    if not name in TOOLS:
+        raise Http404
+
+    return TOOLS[name](request)
+
+
+@admin_page
+def settings_set(request, set_name):
+    set = Setting.sets.get(set_name, {})
+    current_preview = request.session.get('previewing_settings', {})
+
+    if set is None:
+        raise Http404
+
+    if request.POST:
+        form = SettingsSetForm(set, data=request.POST, files=request.FILES)
+
+        if form.is_valid():
+            if 'preview' in request.POST:
+                current_preview.update(form.cleaned_data)
+                request.session['previewing_settings'] = current_preview
+
+                return HttpResponseRedirect(reverse('index'))
+            else:
+                for s in set:
+                    current_preview.pop(s.name, None)
+
+                request.session['previewing_settings'] = current_preview
+
+                if not 'reset' in request.POST:
+                    form.save()
+                    request.user.message_set.create(message=_("'%s' settings saved succesfully") % set_name)
+
+                    if set_name in ('minrep', 'badges', 'repgain'):
+                        settings.SETTINGS_PACK.set_value("custom")
+
+                return HttpResponseRedirect(reverse('admin_set', args=[set_name]))
+    else:
+        form = SettingsSetForm(set, unsaved=current_preview)
+
+    return 'osqaadmin/set.html', {
+    'form': form,
+    'markdown': set.markdown,
+    }
+
+@super_user_required
+def get_default(request, set_name, var_name):
+    set = Setting.sets.get(set_name, None)
+    if set is None: raise Http404
+
+    setting = dict([(s.name, s) for s in set]).get(var_name, None)
+    if setting is None: raise Http404
+
+    setting.to_default()
+
+    if request.is_ajax():
+        return HttpResponse(setting.default)
+    else:
+        return HttpResponseRedirect(reverse('admin_set', kwargs={'set_name': set_name}))
+
+
+def get_recent_activity():
+    return Action.objects.order_by('-action_date')
+
+def get_flagged_posts():
+    return Action.objects.filter(canceled=False, action_type="flag").order_by('-action_date')[0:30]
+
+def get_statistics():
+    return {
+    'total_users': User.objects.all().count(),
+    'users_last_24': User.objects.filter(date_joined__gt=(datetime.now() - timedelta(days=1))).count(),
+    'total_questions': Question.objects.filter_state(deleted=False).count(),
+    'questions_last_24': Question.objects.filter_state(deleted=False).filter(
+            added_at__gt=(datetime.now() - timedelta(days=1))).count(),
+    'total_answers': Answer.objects.filter_state(deleted=False).count(),
+    'answers_last_24': Answer.objects.filter_state(deleted=False).filter(
+            added_at__gt=(datetime.now() - timedelta(days=1))).count(),
+    }
+
+@super_user_required
+def go_bootstrap(request):
+#todo: this is the quick and dirty way of implementing a bootstrap mode
+    try:
+        from forum_modules.default_badges import settings as dbsets
+        dbsets.POPULAR_QUESTION_VIEWS.set_value(100)
+        dbsets.NOTABLE_QUESTION_VIEWS.set_value(200)
+        dbsets.FAMOUS_QUESTION_VIEWS.set_value(300)
+        dbsets.NICE_ANSWER_VOTES_UP.set_value(2)
+        dbsets.NICE_QUESTION_VOTES_UP.set_value(2)
+        dbsets.GOOD_ANSWER_VOTES_UP.set_value(4)
+        dbsets.GOOD_QUESTION_VOTES_UP.set_value(4)
+        dbsets.GREAT_ANSWER_VOTES_UP.set_value(8)
+        dbsets.GREAT_QUESTION_VOTES_UP.set_value(8)
+        dbsets.FAVORITE_QUESTION_FAVS.set_value(1)
+        dbsets.STELLAR_QUESTION_FAVS.set_value(3)
+        dbsets.DISCIPLINED_MIN_SCORE.set_value(3)
+        dbsets.PEER_PRESSURE_MAX_SCORE.set_value(-3)
+        dbsets.CIVIC_DUTY_VOTES.set_value(15)
+        dbsets.PUNDIT_COMMENT_COUNT.set_value(10)
+        dbsets.SELF_LEARNER_UP_VOTES.set_value(2)
+        dbsets.STRUNK_AND_WHITE_EDITS.set_value(10)
+        dbsets.ENLIGHTENED_UP_VOTES.set_value(2)
+        dbsets.GURU_UP_VOTES.set_value(4)
+        dbsets.NECROMANCER_UP_VOTES.set_value(2)
+        dbsets.NECROMANCER_DIF_DAYS.set_value(30)
+        dbsets.TAXONOMIST_USE_COUNT.set_value(5)
+    except:
+        pass
+
+    settings.REP_TO_VOTE_UP.set_value(0)
+    settings.REP_TO_VOTE_DOWN.set_value(15)
+    settings.REP_TO_FLAG.set_value(15)
+    settings.REP_TO_COMMENT.set_value(0)
+    settings.REP_TO_LIKE_COMMENT.set_value(0)
+    settings.REP_TO_UPLOAD.set_value(0)
+    settings.REP_TO_CREATE_TAGS.set_value(0)
+    settings.REP_TO_CLOSE_OWN.set_value(60)
+    settings.REP_TO_REOPEN_OWN.set_value(120)
+    settings.REP_TO_RETAG.set_value(150)
+    settings.REP_TO_EDIT_WIKI.set_value(200)
+    settings.REP_TO_EDIT_OTHERS.set_value(400)
+    settings.REP_TO_CLOSE_OTHERS.set_value(600)
+    settings.REP_TO_DELETE_COMMENTS.set_value(400)
+    settings.REP_TO_VIEW_FLAGS.set_value(30)
+
+    settings.INITIAL_REP.set_value(1)
+    settings.MAX_REP_BY_UPVOTE_DAY.set_value(300)
+    settings.REP_GAIN_BY_UPVOTED.set_value(15)
+    settings.REP_LOST_BY_DOWNVOTED.set_value(1)
+    settings.REP_LOST_BY_DOWNVOTING.set_value(0)
+    settings.REP_GAIN_BY_ACCEPTED.set_value(25)
+    settings.REP_GAIN_BY_ACCEPTING.set_value(5)
+    settings.REP_LOST_BY_FLAGGED.set_value(2)
+    settings.REP_LOST_BY_FLAGGED_3_TIMES.set_value(30)
+    settings.REP_LOST_BY_FLAGGED_5_TIMES.set_value(100)
+
+    settings.SETTINGS_PACK.set_value("bootstrap")
+
+    request.user.message_set.create(message=_('Bootstrap mode enabled'))
+    return HttpResponseRedirect(reverse('admin_index'))
+
+@super_user_required
+def go_defaults(request):
+    for setting in Setting.sets['badges']:
+        setting.to_default()
+    for setting in Setting.sets['minrep']:
+        setting.to_default()
+    for setting in Setting.sets['repgain']:
+        setting.to_default()
+
+    settings.SETTINGS_PACK.set_value("default")
+
+    request.user.message_set.create(message=_('All values reverted to defaults'))
+    return HttpResponseRedirect(reverse('admin_index'))
+
+
+@super_user_required
+def recalculate_denormalized(request):
+    for n in Node.objects.all():
+        n = n.leaf
+        n.score = n.votes.aggregate(score=models.Sum('value'))['score']
+        if not n.score: n.score = 0
+        n.save()
+
+    for u in User.objects.all():
+        u.reputation = u.reputes.aggregate(reputation=models.Sum('value'))['reputation']
+        u.save()
+
+    request.user.message_set.create(message=_('All values recalculated'))
+    return HttpResponseRedirect(reverse('admin_index'))
+
+@admin_page
+def maintenance(request):
+    if request.POST:
+        if 'close' in request.POST or 'adjust' in request.POST:
+            form = MaintenanceModeForm(request.POST)
+
+            if form.is_valid():
+                settings.MAINTAINANCE_MODE.set_value({
+                'allow_ips': form.cleaned_data['ips'],
+                'message': form.cleaned_data['message']})
+
+                if 'close' in request.POST:
+                    message = _('Maintenance mode enabled')
+                else:
+                    message = _('Settings adjusted')
+
+                request.user.message_set.create(message=message)
+
+                return HttpResponseRedirect(reverse('admin_maintenance'))
+        elif 'open' in request.POST:
+            settings.MAINTAINANCE_MODE.set_value(None)
+            request.user.message_set.create(message=_("Your site is now running normally"))
+            return HttpResponseRedirect(reverse('admin_maintenance'))
+    else:
+        form = MaintenanceModeForm(initial={'ips': request.META['REMOTE_ADDR'],
+                                            'message': _('Currently down for maintenance. We\'ll be back soon')})
+
+    return ('osqaadmin/maintenance.html', {'form': form, 'in_maintenance': settings.MAINTAINANCE_MODE.value is not None
+                                           })
+
+
+@admin_page
+def flagged_posts(request):
+    return ('osqaadmin/flagged_posts.html', {
+    'flagged_posts': get_flagged_posts(),
+    })
+
+@admin_page
+def static_pages(request):
+    pages = Page.objects.all()
+
+    return ('osqaadmin/static_pages.html', {
+    'pages': pages,
+    })
+
+@admin_page
+def edit_page(request, id=None):
+    if id:
+        page = get_object_or_404(Page, id=id)
+    else:
+        page = None
+
+    if request.POST:
+        form = PageForm(page, request.POST)
+
+        if form.is_valid():
+            if form.has_changed():
+                if not page:
+                    page = NewPageAction(user=request.user, ip=request.META['REMOTE_ADDR']).save(data=form.cleaned_data
+                                                                                                 ).node
+                else:
+                    EditPageAction(user=request.user, node=page, ip=request.META['REMOTE_ADDR']).save(
+                            data=form.cleaned_data)
+
+            if ('publish' in request.POST) and (not page.published):
+                PublishAction(user=request.user, node=page, ip=request.META['REMOTE_ADDR']).save()
+            elif ('unpublish' in request.POST) and page.published:
+                page.nstate.published.cancel(ip=request.META['REMOTE_ADDR'])
+
+            return HttpResponseRedirect(reverse('admin_edit_page', kwargs={'id': page.id}))
+
+    else:
+        form = PageForm(page)
+
+    if page:
+        published = page.published
+    else:
+        published = False
+
+    return ('osqaadmin/edit_page.html', {
+    'page': page,
+    'form': form,
+    'published': published
+    })
+
+@admin_tools_page(_('createuser'), _("Create new user"))
+def create_user(request):
+    if request.POST:
+        form = CreateUserForm(request.POST)
+
+        if form.is_valid():
+            user_ = User(username=form.cleaned_data['username'], email=form.cleaned_data['email'])
+            user_.set_password(form.cleaned_data['password1'])
+
+            if not form.cleaned_data.get('validate_email', False):
+                user_.email_isvalid = True
+
+            user_.save()
+            UserJoinsAction(user=user_).save()
+
+            request.user.message_set.create(message=_("New user created sucessfully. %s.") % html.hyperlink(
+                    user_.get_profile_url(), _("See %s profile") % user_.username, target="_blank"))
+
+            return HttpResponseRedirect(reverse("admin_tools", kwargs={'name': 'createuser'}))
+    else:
+        form = CreateUserForm()
+
+    return ('osqaadmin/createuser.html', {
+        'form': form,
+    })
+
+class NodeManagementPaginatorContext(pagination.PaginatorContext):
+    def __init__(self, id='QUESTIONS_LIST', prefix='', default_pagesize=100):
+        super (NodeManagementPaginatorContext, self).__init__(id, sort_methods=(
+            (_('added_at'), pagination.SimpleSort(_('added_at'), '-added_at', "")),
+            (_('added_at_asc'), pagination.SimpleSort(_('added_at_asc'), 'added_at', "")),
+            (_('author'), pagination.SimpleSort(_('author'), '-author__username', "")),
+            (_('author_asc'), pagination.SimpleSort(_('author_asc'), 'author__username', "")),
+            (_('score'), pagination.SimpleSort(_('score'), '-score', "")),
+            (_('score_asc'), pagination.SimpleSort(_('score_asc'), 'score', "")),
+            (_('act_at'), pagination.SimpleSort(_('act_at'), '-last_activity_at', "")),
+            (_('act_at_asc'), pagination.SimpleSort(_('act_at_asc'), 'last_activity_at', "")),
+            (_('act_by'), pagination.SimpleSort(_('act_by'), '-last_activity_by__username', "")),
+            (_('act_by_asc'), pagination.SimpleSort(_('act_by_asc'), 'last_activity_by__username', "")),
+        ), pagesizes=(default_pagesize,), force_sort='added_at', default_pagesize=default_pagesize, prefix=prefix)
+
+@admin_tools_page(_("nodeman"), _("Bulk management"))
+def node_management(request):
+    if request.POST:
+        params = pagination.generate_uri(request.GET, ('page',))
+
+        if "save_filter" in request.POST:
+            filter_name = request.POST.get('filter_name', _('filter'))
+            params = pagination.generate_uri(request.GET, ('page',))
+            current_filters = settings.NODE_MAN_FILTERS.value
+            current_filters.append((filter_name, params))
+            settings.NODE_MAN_FILTERS.set_value(current_filters)
+
+        elif r"execute" in request.POST:
+            selected_nodes = request.POST.getlist('_selected_node')
+
+            if selected_nodes and request.POST.get('action', None):
+                action = request.POST['action']
+                selected_nodes = Node.objects.filter(id__in=selected_nodes)
+
+                message = _("No action performed")
+
+                if action == 'delete_selected':
+                    for node in selected_nodes:
+                        if node.node_type in ('question', 'answer', 'comment') and (not node.nis.deleted):
+                            DeleteAction(user=request.user, node=node, ip=request.META['REMOTE_ADDR']).save()
+
+                    message = _("All selected nodes marked as deleted")
+
+                if action == 'undelete_selected':
+                    for node in selected_nodes:
+                        if node.node_type in ('question', 'answer', 'comment') and (node.nis.deleted):
+                            node.nstate.deleted.cancel(ip=request.META['REMOTE_ADDR'])
+
+                    message = _("All selected nodes undeleted")
+
+                if action == "close_selected":
+                    for node in selected_nodes:
+                        if node.node_type == "question" and (not node.nis.closed):
+                            CloseAction(node=node.leaf, user=request.user, extra=_("bulk close"), ip=request.META['REMOTE_ADDR']).save()
+
+                    message = _("Selected questions were closed")
+
+                if action == "hard_delete_selected":
+                    ids = [n.id for n in selected_nodes]
+
+                    for id in ids:
+                        try:
+                            node = Node.objects.get(id=id)
+                            node.delete()
+                        except:
+                            pass
+
+                    message = _("All selected nodes deleted")
+
+                request.user.message_set.create(message=message)
+
+                params = pagination.generate_uri(request.GET, ('page',))
+                
+            return HttpResponseRedirect(reverse("admin_tools", kwargs={'name': 'nodeman'}) + "?" + params)
+
+
+    nodes = Node.objects.all()
+
+    text = request.GET.get('text', '')
+    text_in = request.GET.get('text_in', 'body')
+
+    authors = request.GET.getlist('authors')
+    tags = request.GET.getlist('tags')
+
+    type_filter = request.GET.getlist('node_type')
+    state_filter = request.GET.getlist('state_type')
+    state_filter_type = request.GET.get('state_filter_type', 'any')
+
+    if type_filter:
+        nodes = nodes.filter(node_type__in=type_filter)
+
+    state_types = NodeState.objects.filter(node__in=nodes).values_list('state_type', flat=True).distinct('state_type')
+    state_filter = [s for s in state_filter if s in state_types]
+
+    if state_filter:
+        if state_filter_type == 'all':
+            nodes = nodes.all_states(*state_filter)
+        else:
+            nodes = nodes.any_state(*state_filter)
+
+    if (authors):
+        nodes = nodes.filter(author__id__in=authors)
+        authors = User.objects.filter(id__in=authors)
+
+    if (tags):
+        nodes = nodes.filter(tags__id__in=tags)
+        tags = Tag.objects.filter(id__in=tags)
+
+    if text:
+        text_in = request.GET.get('text_in', 'body')
+        filter = None
+
+        if text_in == 'title' or text_in == 'both':
+            filter = models.Q(title__icontains=text)
+
+        if text_in == 'body' or text_in == 'both':
+            sec_filter = models.Q(body__icontains=text)
+            if filter:
+                filter = filter | sec_filter
+            else:
+                filter = sec_filter
+
+        if filter:
+            nodes = nodes.filter(filter)
+
+    node_types = [(k, n.friendly_name) for k, n in NodeMetaClass.types.items()]
+
+    return ('osqaadmin/nodeman.html', pagination.paginated(request, ("nodes", NodeManagementPaginatorContext()), {
+    'nodes': nodes,
+    'text': text,
+    'text_in': text_in,
+    'type_filter': type_filter,
+    'state_filter': state_filter,
+    'state_filter_type': state_filter_type,
+    'node_types': node_types,
+    'state_types': state_types,
+    'authors': authors,
+    'tags': tags,
+    'hide_menu': True
+    }))
+
+
+
+
+
diff --git a/forum/modules/template_loader.py/forum/views/auth.py b/forum/modules/template_loader.py/forum/views/auth.py
new file mode 100644 (file)
index 0000000..3281fe4
--- /dev/null
@@ -0,0 +1,422 @@
+from django.shortcuts import render_to_response, get_object_or_404
+from django.template import RequestContext
+from django.core.urlresolvers import reverse
+from forum.models import User
+from django.http import HttpResponseRedirect, Http404
+from forum.http_responses import HttpResponseUnauthorized
+from django.utils.safestring import mark_safe
+from django.utils.translation import ugettext as _
+from django.utils.http import urlquote_plus
+from forum.views.decorators import login_required
+from forum.modules import decorate
+from django.contrib.auth import login, logout
+from django.http import get_host
+from forum.actions import SuspendAction
+from forum.utils import html
+from forum import settings
+from writers import manage_pending_data
+import types
+import datetime
+import logging
+
+from forum.forms import SimpleRegistrationForm, SimpleEmailSubscribeForm, \
+        TemporaryLoginRequestForm, ChangePasswordForm, SetPasswordForm
+from forum.utils.mail import send_template_email
+
+from forum.authentication.base import InvalidAuthentication
+from forum.authentication import AUTH_PROVIDERS
+
+from forum.models import AuthKeyUserAssociation, ValidationHash, Question, Answer
+from forum.actions import UserJoinsAction
+
+def signin_page(request):
+    referer = request.META.get('HTTP_REFERER', '/')
+
+    # If the referer is equal to the sign up page, e. g. if the previous login attempt was not successful we do not
+    # change the sign in URL. The user should go to the same page.
+    if not referer.replace(settings.APP_URL, '') == reverse('auth_signin'):
+        request.session['on_signin_url'] = referer
+
+    all_providers = [provider.context for provider in AUTH_PROVIDERS.values()]
+
+    sort = lambda c1, c2: c1.weight - c2.weight
+    can_show = lambda c: not request.user.is_authenticated() or c.show_to_logged_in_user
+
+    bigicon_providers = sorted([
+    context for context in all_providers if context.mode == 'BIGICON' and can_show(context)
+    ], sort)
+
+    smallicon_providers = sorted([
+    context for context in all_providers if context.mode == 'SMALLICON' and can_show(context)
+    ], sort)
+
+    top_stackitem_providers = sorted([
+    context for context in all_providers if context.mode == 'TOP_STACK_ITEM' and can_show(context)
+    ], sort)
+
+    stackitem_providers = sorted([
+    context for context in all_providers if context.mode == 'STACK_ITEM' and can_show(context)
+    ], sort)
+
+    try:
+        msg = request.session['auth_error']
+        del request.session['auth_error']
+    except:
+        msg = None
+
+    return render_to_response(
+            'auth/signin.html',
+            {
+            'msg': msg,
+            'all_providers': all_providers,
+            'bigicon_providers': bigicon_providers,
+            'top_stackitem_providers': top_stackitem_providers,
+            'stackitem_providers': stackitem_providers,
+            'smallicon_providers': smallicon_providers,
+            },
+            RequestContext(request))
+
+def prepare_provider_signin(request, provider):
+    force_email_request = request.REQUEST.get('validate_email', 'yes') == 'yes'
+    request.session['force_email_request'] = force_email_request
+
+    if provider in AUTH_PROVIDERS:
+        provider_class = AUTH_PROVIDERS[provider].consumer
+
+        try:
+            request_url = provider_class.prepare_authentication_request(request,
+                                                                        reverse('auth_provider_done',
+                                                                                kwargs={'provider': provider}))
+
+            return HttpResponseRedirect(request_url)
+        except NotImplementedError, e:
+            return process_provider_signin(request, provider)
+        except InvalidAuthentication, e:
+            request.session['auth_error'] = e.message
+
+        return HttpResponseRedirect(reverse('auth_signin'))
+    else:
+        raise Http404()
+
+
+def process_provider_signin(request, provider):
+    if provider in AUTH_PROVIDERS:
+        provider_class = AUTH_PROVIDERS[provider].consumer
+
+        try:
+            assoc_key = provider_class.process_authentication_request(request)
+        except InvalidAuthentication, e:
+            request.session['auth_error'] = e.message
+            return HttpResponseRedirect(reverse('auth_signin'))
+
+        if request.user.is_authenticated():
+            if isinstance(assoc_key, (type, User)):
+                if request.user != assoc_key:
+                    request.session['auth_error'] = _(
+                            "Sorry, these login credentials belong to anoother user. Plese terminate your current session and try again."
+                            )
+                else:
+                    request.session['auth_error'] = _("You are already logged in with that user.")
+            else:
+                try:
+                    assoc = AuthKeyUserAssociation.objects.get(key=assoc_key)
+                    if assoc.user == request.user:
+                        request.session['auth_error'] = _(
+                                "These login credentials are already associated with your account.")
+                    else:
+                        request.session['auth_error'] = _(
+                                "Sorry, these login credentials belong to anoother user. Plese terminate your current session and try again."
+                                )
+                except:
+                    uassoc = AuthKeyUserAssociation(user=request.user, key=assoc_key, provider=provider)
+                    uassoc.save()
+                    request.user.message_set.create(
+                            message=_('The new credentials are now associated with your account'))
+                    return HttpResponseRedirect(reverse('user_authsettings', args=[request.user.id]))
+
+            return HttpResponseRedirect(reverse('auth_signin'))
+        else:
+            if isinstance(assoc_key, User):
+                return login_and_forward(request, assoc_key)
+
+        try:
+            assoc = AuthKeyUserAssociation.objects.get(key=assoc_key)
+            user_ = assoc.user
+            return login_and_forward(request, user_)
+        except:
+            request.session['assoc_key'] = assoc_key
+            request.session['auth_provider'] = provider
+            return HttpResponseRedirect(reverse('auth_external_register'))
+
+    return HttpResponseRedirect(reverse('auth_signin'))
+
+def external_register(request):
+    if request.method == 'POST' and 'bnewaccount' in request.POST:
+        form1 = SimpleRegistrationForm(request.POST)
+        email_feeds_form = SimpleEmailSubscribeForm(request.POST)
+
+        if (form1.is_valid() and email_feeds_form.is_valid()):
+            user_ = User(username=form1.cleaned_data['username'], email=form1.cleaned_data['email'])
+            user_.email_isvalid = request.session.get('auth_validated_email', '') == form1.cleaned_data['email']
+            user_.set_unusable_password()
+
+            if User.objects.all().count() == 0:
+                user_.is_superuser = True
+                user_.is_staff = True
+
+            user_.save()
+            UserJoinsAction(user=user_, ip=request.META['REMOTE_ADDR']).save()
+
+            try:
+                assoc_key = request.session['assoc_key']
+                auth_provider = request.session['auth_provider']
+            except:
+                request.session['auth_error'] = _(
+                        "Oops, something went wrong in the middle of this process. Please try again. Note that you need to have cookies enabled for the authentication to work."
+                        )
+                logging.error("Missing session data when trying to complete user registration: %s" % ", ".join(
+                        ["%s: %s" % (k, v) for k, v in request.META.items()]))
+                return HttpResponseRedirect(reverse('auth_signin'))
+
+            uassoc = AuthKeyUserAssociation(user=user_, key=assoc_key, provider=auth_provider)
+            uassoc.save()
+
+            if email_feeds_form.cleaned_data['subscribe'] == 'n':
+                user_.subscription_settings.enable_notifications = False
+                user_.subscription_settings.save()
+
+            del request.session['assoc_key']
+            del request.session['auth_provider']
+
+            return login_and_forward(request, user_, message=_("A welcome email has been sent to your email address. "))
+    else:
+        auth_provider = request.session.get('auth_provider', None)
+        if not auth_provider:
+            request.session['auth_error'] = _(
+                    "Oops, something went wrong in the middle of this process. Please try again.")
+            logging.error("Missing session data when trying to complete user registration: %s" % ", ".join(
+                    ["%s: %s" % (k, v) for k, v in request.META.items()]))
+            return HttpResponseRedirect(reverse('auth_signin'))
+
+        provider_class = AUTH_PROVIDERS[auth_provider].consumer
+        user_data = provider_class.get_user_data(request.session['assoc_key'])
+
+        if not user_data:
+            user_data = request.session.get('auth_consumer_data', {})
+
+        username = user_data.get('username', '')
+        email = user_data.get('email', '')
+
+        if email:
+            request.session['auth_validated_email'] = email
+
+        form1 = SimpleRegistrationForm(initial={
+        'next': '/',
+        'username': username,
+        'email': email,
+        })
+        email_feeds_form = SimpleEmailSubscribeForm()
+
+    provider_context = AUTH_PROVIDERS[request.session['auth_provider']].context
+
+    return render_to_response('auth/complete.html', {
+    'form1': form1,
+    'email_feeds_form': email_feeds_form,
+    'provider':mark_safe(provider_context.human_name),
+    'login_type':provider_context.id,
+    'gravatar_faq_url':reverse('faq') + '#gravatar',
+    }, context_instance=RequestContext(request))
+
+def request_temp_login(request):
+    if request.method == 'POST':
+        form = TemporaryLoginRequestForm(request.POST)
+
+        if form.is_valid():
+            users = form.user_cache
+
+            for u in users:
+                if u.is_suspended():
+                    return forward_suspended_user(request, u, False)
+
+            for u in users:
+                try:
+                    hash = get_object_or_404(ValidationHash, user=u, type='templogin')
+                    if hash.expiration < datetime.datetime.now():
+                        hash.delete()
+                        return request_temp_login(request)
+                except:
+                    hash = ValidationHash.objects.create_new(u, 'templogin', [u.id])
+
+                send_template_email([u], "auth/temp_login_email.html", {'temp_login_code': hash})
+
+                request.user.message_set.create(message=_("An email has been sent with your temporary login key"))
+
+            return HttpResponseRedirect(reverse('index'))
+    else:
+        form = TemporaryLoginRequestForm()
+
+    return render_to_response(
+            'auth/temp_login_request.html', {'form': form},
+            context_instance=RequestContext(request))
+
+def temp_signin(request, user, code):
+    user = get_object_or_404(User, id=user)
+
+    if (ValidationHash.objects.validate(code, user, 'templogin', [user.id])):
+        
+        # If the user requests temp_signin he must have forgotten his password. So we mark it as unusable.
+        user.set_unusable_password()
+        user.save()
+        
+        return login_and_forward(request, user, reverse('user_authsettings', kwargs={'id': user.id}),
+                                 _(
+                                         "You are logged in with a temporary access key, please take the time to fix your issue with authentication."
+                                         ))
+    else:
+        raise Http404()
+
+def send_validation_email(request):
+    if not request.user.is_authenticated():
+        return HttpResponseUnauthorized(request)
+    else:
+        # We check if there are some old validation hashes. If there are -- we delete them.
+        try:
+            hash = ValidationHash.objects.get(user=request.user, type='email')
+            hash.delete()
+        except:
+            pass
+
+        # We don't care if there are previous cashes in the database... In every case we have to create a new one
+        hash = ValidationHash.objects.create_new(request.user, 'email', [request.user.email])
+
+        send_template_email([request.user], "auth/mail_validation.html", {'validation_code': hash})
+        request.user.message_set.create(message=_("A message with an email validation link was just sent to your address."))
+        return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
+
+        
+
+def validate_email(request, user, code):
+    user = get_object_or_404(User, id=user)
+
+    if (ValidationHash.objects.validate(code, user, 'email', [user.email])):
+        user.email_isvalid = True
+        user.save()
+        return login_and_forward(request, user, reverse('index'), _("Thank you, your email is now validated."))
+    else:
+        return render_to_response('auth/mail_already_validated.html', { 'user' : user }, RequestContext(request))
+
+def auth_settings(request, id):
+    user_ = get_object_or_404(User, id=id)
+
+    if not (request.user.is_superuser or request.user == user_):
+        return HttpResponseUnauthorized(request)
+
+    auth_keys = user_.auth_keys.all()
+
+    if request.user.is_superuser or (not user_.has_usable_password()):
+        FormClass = SetPasswordForm
+    else:
+        FormClass = ChangePasswordForm
+
+    if request.POST:
+        form = FormClass(request.POST, user=user_)
+        if form.is_valid():
+            is_new_pass = not user_.has_usable_password()
+            user_.set_password(form.cleaned_data['password1'])
+            user_.save()
+
+            if is_new_pass:
+                request.user.message_set.create(message=_("New password set"))
+                if not request.user.is_superuser:
+                    form = ChangePasswordForm(user=user_)
+            else:
+                request.user.message_set.create(message=_("Your password was changed"))
+
+            return HttpResponseRedirect(reverse('user_authsettings', kwargs={'id': user_.id}))
+    else:
+        form = FormClass(user=user_)
+
+    auth_keys_list = []
+
+    for k in auth_keys:
+        provider = AUTH_PROVIDERS.get(k.provider, None)
+
+        if provider is not None:
+            name =  "%s: %s" % (provider.context.human_name, provider.context.readable_key(k))
+        else:
+            from forum.authentication.base import ConsumerTemplateContext
+            "unknown: %s" % ConsumerTemplateContext.readable_key(k)
+
+        auth_keys_list.append({
+        'name': name,
+        'id': k.id
+        })
+
+    return render_to_response('auth/auth_settings.html', {
+    'view_user': user_,
+    "can_view_private": (user_ == request.user) or request.user.is_superuser,
+    'form': form,
+    'has_password': user_.has_usable_password(),
+    'auth_keys': auth_keys_list,
+    'allow_local_auth': AUTH_PROVIDERS.get('local', None),
+    }, context_instance=RequestContext(request))
+
+def remove_external_provider(request, id):
+    association = get_object_or_404(AuthKeyUserAssociation, id=id)
+    if not (request.user.is_superuser or request.user == association.user):
+        return HttpResponseUnauthorized(request)
+
+    request.user.message_set.create(message=_("You removed the association with %s") % association.provider)
+    association.delete()
+    return HttpResponseRedirect(reverse('user_authsettings', kwargs={'id': association.user.id}))
+
+def login_and_forward(request, user, forward=None, message=None):
+    if user.is_suspended():
+        return forward_suspended_user(request, user)
+
+    user.backend = "django.contrib.auth.backends.ModelBackend"
+    login(request, user)
+
+    if message is None:
+        message = _("Welcome back %s, you are now logged in") % user.username
+
+    request.user.message_set.create(message=message)
+
+    if not forward:
+        forward = request.session.get('on_signin_url', reverse('index'))
+
+    pending_data = request.session.get('pending_submission_data', None)
+
+    if pending_data and (user.email_isvalid or pending_data['type'] not in settings.REQUIRE_EMAIL_VALIDATION_TO):
+        submission_time = pending_data['time']
+        if submission_time < datetime.datetime.now() - datetime.timedelta(minutes=int(settings.HOLD_PENDING_POSTS_MINUTES)):
+            del request.session['pending_submission_data']
+        elif submission_time < datetime.datetime.now() - datetime.timedelta(minutes=int(settings.WARN_PENDING_POSTS_MINUTES)):
+            user.message_set.create(message=(_("You have a %s pending submission.") % pending_data['data_name']) + " %s, %s, %s" % (
+                html.hyperlink(reverse('manage_pending_data', kwargs={'action': _('save')}), _("save it")),
+                html.hyperlink(reverse('manage_pending_data', kwargs={'action': _('review')}), _("review")),
+                html.hyperlink(reverse('manage_pending_data', kwargs={'action': _('cancel')}), _("cancel"))
+            ))
+        else:
+            return manage_pending_data(request, _('save'), forward)
+
+    return HttpResponseRedirect(forward)
+
+def forward_suspended_user(request, user, show_private_msg=True):
+    message = _("Sorry, but this account is suspended")
+    if show_private_msg:
+        msg_type = 'privatemsg'
+    else:
+        msg_type = 'publicmsg'
+
+    suspension = user.suspension
+    if suspension:
+        message += (":<br />" + suspension.extra.get(msg_type, ''))
+
+    request.user.message_set.create(message)
+    return HttpResponseRedirect(reverse('index'))
+
+@decorate.withfn(login_required)
+def signout(request):
+    logout(request)
+    return HttpResponseRedirect(reverse('index'))
diff --git a/forum/modules/template_loader.py/forum/views/commands.py b/forum/modules/template_loader.py/forum/views/commands.py
new file mode 100644 (file)
index 0000000..af6ad64
--- /dev/null
@@ -0,0 +1,578 @@
+import datetime
+from forum import settings
+from django.core.exceptions import ObjectDoesNotExist
+from django.utils import simplejson
+from django.http import HttpResponse, HttpResponseRedirect, Http404
+from django.shortcuts import get_object_or_404, render_to_response
+from django.utils.translation import ungettext, ugettext as _
+from django.template import RequestContext
+from forum.models import *
+from forum.models.node import NodeMetaClass
+from forum.actions import *
+from django.core.urlresolvers import reverse
+from forum.utils.decorators import ajax_method, ajax_login_required
+from decorators import command, CommandException, RefreshPageCommand
+from forum.modules import decorate
+from forum import settings
+import logging
+
+class NotEnoughRepPointsException(CommandException):
+    def __init__(self, action):
+        super(NotEnoughRepPointsException, self).__init__(
+                _(
+                        """Sorry, but you don't have enough reputation points to %(action)s.<br />Please check the <a href='%(faq_url)s'>faq</a>"""
+                        ) % {'action': action, 'faq_url': reverse('faq')}
+                )
+
+class CannotDoOnOwnException(CommandException):
+    def __init__(self, action):
+        super(CannotDoOnOwnException, self).__init__(
+                _(
+                        """Sorry but you cannot %(action)s your own post.<br />Please check the <a href='%(faq_url)s'>faq</a>"""
+                        ) % {'action': action, 'faq_url': reverse('faq')}
+                )
+
+class AnonymousNotAllowedException(CommandException):
+    def __init__(self, action):
+        super(AnonymousNotAllowedException, self).__init__(
+                _(
+                        """Sorry but anonymous users cannot %(action)s.<br />Please login or create an account <a href='%(signin_url)s'>here</a>."""
+                        ) % {'action': action, 'signin_url': reverse('auth_signin')}
+                )
+
+class NotEnoughLeftException(CommandException):
+    def __init__(self, action, limit):
+        super(NotEnoughLeftException, self).__init__(
+                _(
+                        """Sorry, but you don't have enough %(action)s left for today..<br />The limit is %(limit)s per day..<br />Please check the <a href='%(faq_url)s'>faq</a>"""
+                        ) % {'action': action, 'limit': limit, 'faq_url': reverse('faq')}
+                )
+
+class CannotDoubleActionException(CommandException):
+    def __init__(self, action):
+        super(CannotDoubleActionException, self).__init__(
+                _(
+                        """Sorry, but you cannot %(action)s twice the same post.<br />Please check the <a href='%(faq_url)s'>faq</a>"""
+                        ) % {'action': action, 'faq_url': reverse('faq')}
+                )
+
+
+@decorate.withfn(command)
+def vote_post(request, id, vote_type):
+    post = get_object_or_404(Node, id=id).leaf
+    user = request.user
+
+    if not user.is_authenticated():
+        raise AnonymousNotAllowedException(_('vote'))
+
+    if user == post.author:
+        raise CannotDoOnOwnException(_('vote'))
+
+    if not (vote_type == 'up' and user.can_vote_up() or user.can_vote_down()):
+        raise NotEnoughRepPointsException(vote_type == 'up' and _('upvote') or _('downvote'))
+
+    user_vote_count_today = user.get_vote_count_today()
+
+    if user_vote_count_today >= user.can_vote_count_today():
+        raise NotEnoughLeftException(_('votes'), str(settings.MAX_VOTES_PER_DAY))
+
+    new_vote_cls = (vote_type == 'up') and VoteUpAction or VoteDownAction
+    score_inc = 0
+
+    old_vote = VoteAction.get_action_for(node=post, user=user)
+
+    if old_vote:
+        if old_vote.action_date < datetime.datetime.now() - datetime.timedelta(days=int(settings.DENY_UNVOTE_DAYS)):
+            raise CommandException(
+                    _("Sorry but you cannot cancel a vote after %(ndays)d %(tdays)s from the original vote") %
+                    {'ndays': int(settings.DENY_UNVOTE_DAYS),
+                     'tdays': ungettext('day', 'days', int(settings.DENY_UNVOTE_DAYS))}
+                    )
+
+        old_vote.cancel(ip=request.META['REMOTE_ADDR'])
+        score_inc += (old_vote.__class__ == VoteDownAction) and 1 or -1
+
+    if old_vote.__class__ != new_vote_cls:
+        new_vote_cls(user=user, node=post, ip=request.META['REMOTE_ADDR']).save()
+        score_inc += (new_vote_cls == VoteUpAction) and 1 or -1
+    else:
+        vote_type = "none"
+
+    response = {
+    'commands': {
+    'update_post_score': [id, score_inc],
+    'update_user_post_vote': [id, vote_type]
+    }
+    }
+
+    votes_left = (int(settings.MAX_VOTES_PER_DAY) - user_vote_count_today) + (vote_type == 'none' and -1 or 1)
+
+    if int(settings.START_WARN_VOTES_LEFT) >= votes_left:
+        response['message'] = _("You have %(nvotes)s %(tvotes)s left today.") % \
+                    {'nvotes': votes_left, 'tvotes': ungettext('vote', 'votes', votes_left)}
+
+    return response
+
+@decorate.withfn(command)
+def flag_post(request, id):
+    if not request.POST:
+        return render_to_response('node/report.html', {'types': settings.FLAG_TYPES})
+
+    post = get_object_or_404(Node, id=id)
+    user = request.user
+
+    if not user.is_authenticated():
+        raise AnonymousNotAllowedException(_('flag posts'))
+
+    if user == post.author:
+        raise CannotDoOnOwnException(_('flag'))
+
+    if not (user.can_flag_offensive(post)):
+        raise NotEnoughRepPointsException(_('flag posts'))
+
+    user_flag_count_today = user.get_flagged_items_count_today()
+
+    if user_flag_count_today >= int(settings.MAX_FLAGS_PER_DAY):
+        raise NotEnoughLeftException(_('flags'), str(settings.MAX_FLAGS_PER_DAY))
+
+    try:
+        current = FlagAction.objects.get(canceled=False, user=user, node=post)
+        raise CommandException(
+                _("You already flagged this post with the following reason: %(reason)s") % {'reason': current.extra})
+    except ObjectDoesNotExist:
+        reason = request.POST.get('prompt', '').strip()
+
+        if not len(reason):
+            raise CommandException(_("Reason is empty"))
+
+        FlagAction(user=user, node=post, extra=reason, ip=request.META['REMOTE_ADDR']).save()
+
+    return {'message': _("Thank you for your report. A moderator will review your submission shortly.")}
+
+@decorate.withfn(command)
+def like_comment(request, id):
+    comment = get_object_or_404(Comment, id=id)
+    user = request.user
+
+    if not user.is_authenticated():
+        raise AnonymousNotAllowedException(_('like comments'))
+
+    if user == comment.user:
+        raise CannotDoOnOwnException(_('like'))
+
+    if not user.can_like_comment(comment):
+        raise NotEnoughRepPointsException( _('like comments'))
+
+    like = VoteAction.get_action_for(node=comment, user=user)
+
+    if like:
+        like.cancel(ip=request.META['REMOTE_ADDR'])
+        likes = False
+    else:
+        VoteUpCommentAction(node=comment, user=user, ip=request.META['REMOTE_ADDR']).save()
+        likes = True
+
+    return {
+    'commands': {
+    'update_post_score': [comment.id, likes and 1 or -1],
+    'update_user_post_vote': [comment.id, likes and 'up' or 'none']
+    }
+    }
+
+@decorate.withfn(command)
+def delete_comment(request, id):
+    comment = get_object_or_404(Comment, id=id)
+    user = request.user
+
+    if not user.is_authenticated():
+        raise AnonymousNotAllowedException(_('delete comments'))
+
+    if not user.can_delete_comment(comment):
+        raise NotEnoughRepPointsException( _('delete comments'))
+
+    if not comment.nis.deleted:
+        DeleteAction(node=comment, user=user, ip=request.META['REMOTE_ADDR']).save()
+
+    return {
+    'commands': {
+    'remove_comment': [comment.id],
+    }
+    }
+
+@decorate.withfn(command)
+def mark_favorite(request, id):
+    question = get_object_or_404(Question, id=id)
+
+    if not request.user.is_authenticated():
+        raise AnonymousNotAllowedException(_('mark a question as favorite'))
+
+    try:
+        favorite = FavoriteAction.objects.get(canceled=False, node=question, user=request.user)
+        favorite.cancel(ip=request.META['REMOTE_ADDR'])
+        added = False
+    except ObjectDoesNotExist:
+        FavoriteAction(node=question, user=request.user, ip=request.META['REMOTE_ADDR']).save()
+        added = True
+
+    return {
+    'commands': {
+    'update_favorite_count': [added and 1 or -1],
+    'update_favorite_mark': [added and 'on' or 'off']
+    }
+    }
+
+@decorate.withfn(command)
+def comment(request, id):
+    post = get_object_or_404(Node, id=id)
+    user = request.user
+
+    if not user.is_authenticated():
+        raise AnonymousNotAllowedException(_('comment'))
+
+    if not request.method == 'POST':
+        raise CommandException(_("Invalid request"))
+
+    comment_text = request.POST.get('comment', '').strip()
+
+    if not len(comment_text):
+        raise CommandException(_("Comment is empty"))
+
+    if len(comment_text) < settings.FORM_MIN_COMMENT_BODY:
+        raise CommandException(_("At least %d characters required on comment body.") % settings.FORM_MIN_COMMENT_BODY)
+
+    if len(comment_text) > settings.FORM_MAX_COMMENT_BODY:
+        raise CommandException(_("No more than %d characters on comment body.") % settings.FORM_MAX_COMMENT_BODY)
+
+    if 'id' in request.POST:
+        comment = get_object_or_404(Comment, id=request.POST['id'])
+
+        if not user.can_edit_comment(comment):
+            raise NotEnoughRepPointsException( _('edit comments'))
+
+        comment = ReviseAction(user=user, node=comment, ip=request.META['REMOTE_ADDR']).save(
+                data=dict(text=comment_text)).node
+    else:
+        if not user.can_comment(post):
+            raise NotEnoughRepPointsException( _('comment'))
+
+        comment = CommentAction(user=user, ip=request.META['REMOTE_ADDR']).save(
+                data=dict(text=comment_text, parent=post)).node
+
+    if comment.active_revision.revision == 1:
+        return {
+        'commands': {
+        'insert_comment': [
+                id, comment.id, comment.comment, user.decorated_name, user.get_profile_url(),
+                reverse('delete_comment', kwargs={'id': comment.id}),
+                reverse('node_markdown', kwargs={'id': comment.id}),
+                reverse('convert_comment', kwargs={'id': comment.id}),            
+                ]
+        }
+        }
+    else:
+        return {
+        'commands': {
+        'update_comment': [comment.id, comment.comment]
+        }
+        }
+
+@decorate.withfn(command)
+def node_markdown(request, id):
+    user = request.user
+
+    if not user.is_authenticated():
+        raise AnonymousNotAllowedException(_('accept answers'))
+
+    node = get_object_or_404(Node, id=id)
+    return HttpResponse(node.active_revision.body, mimetype="text/plain")
+
+
+@decorate.withfn(command)
+def accept_answer(request, id):
+    if settings.DISABLE_ACCEPTING_FEATURE:
+        raise Http404()
+
+    user = request.user
+
+    if not user.is_authenticated():
+        raise AnonymousNotAllowedException(_('accept answers'))
+
+    answer = get_object_or_404(Answer, id=id)
+    question = answer.question
+
+    if not user.can_accept_answer(answer):
+        raise CommandException(_("Sorry but you cannot accept the answer"))
+
+    commands = {}
+
+    if answer.nis.accepted:
+        answer.nstate.accepted.cancel(user, ip=request.META['REMOTE_ADDR'])
+        commands['unmark_accepted'] = [answer.id]
+    else:
+        if settings.MAXIMUM_ACCEPTED_ANSWERS and (question.accepted_count >= settings.MAXIMUM_ACCEPTED_ANSWERS):
+            raise CommandException(ungettext("This question already has an accepted answer.",
+                "Sorry but this question has reached the limit of accepted answers.", int(settings.MAXIMUM_ACCEPTED_ANSWERS)))
+
+        if settings.MAXIMUM_ACCEPTED_PER_USER and question.accepted_count:
+            accepted_from_author = question.accepted_answers.filter(author=answer.author).count()
+
+            if accepted_from_author >= settings.MAXIMUM_ACCEPTED_PER_USER:
+                raise CommandException(ungettext("The author of this answer already has an accepted answer in this question.",
+                "Sorry but the author of this answer has reached the limit of accepted answers per question.", int(settings.MAXIMUM_ACCEPTED_PER_USER)))             
+
+
+        AcceptAnswerAction(node=answer, user=user, ip=request.META['REMOTE_ADDR']).save()
+        commands['mark_accepted'] = [answer.id]
+
+    return {'commands': commands}
+
+@decorate.withfn(command)
+def delete_post(request, id):
+    post = get_object_or_404(Node, id=id)
+    user = request.user
+
+    if not user.is_authenticated():
+        raise AnonymousNotAllowedException(_('delete posts'))
+
+    if not (user.can_delete_post(post)):
+        raise NotEnoughRepPointsException(_('delete posts'))
+
+    ret = {'commands': {}}
+
+    if post.nis.deleted:
+        post.nstate.deleted.cancel(user, ip=request.META['REMOTE_ADDR'])
+        ret['commands']['unmark_deleted'] = [post.node_type, id]
+    else:
+        DeleteAction(node=post, user=user, ip=request.META['REMOTE_ADDR']).save()
+
+        ret['commands']['mark_deleted'] = [post.node_type, id]
+
+    return ret
+
+@decorate.withfn(command)
+def close(request, id, close):
+    if close and not request.POST:
+        return render_to_response('node/report.html', {'types': settings.CLOSE_TYPES})
+
+    question = get_object_or_404(Question, id=id)
+    user = request.user
+
+    if not user.is_authenticated():
+        raise AnonymousNotAllowedException(_('close questions'))
+
+    if question.nis.closed:
+        if not user.can_reopen_question(question):
+            raise NotEnoughRepPointsException(_('reopen questions'))
+
+        question.nstate.closed.cancel(user, ip=request.META['REMOTE_ADDR'])
+    else:
+        if not request.user.can_close_question(question):
+            raise NotEnoughRepPointsException(_('close questions'))
+
+        reason = request.POST.get('prompt', '').strip()
+
+        if not len(reason):
+            raise CommandException(_("Reason is empty"))
+
+        CloseAction(node=question, user=user, extra=reason, ip=request.META['REMOTE_ADDR']).save()
+
+    return RefreshPageCommand()
+
+@decorate.withfn(command)
+def wikify(request, id):
+    node = get_object_or_404(Node, id=id)
+    user = request.user
+
+    if not user.is_authenticated():
+        raise AnonymousNotAllowedException(_('mark posts as community wiki'))
+
+    if node.nis.wiki:
+        if not user.can_cancel_wiki(node):
+            raise NotEnoughRepPointsException(_('cancel a community wiki post'))
+
+        if node.nstate.wiki.action_type == "wikify":
+            node.nstate.wiki.cancel()
+        else:
+            node.nstate.wiki = None
+    else:
+        if not user.can_wikify(node):
+            raise NotEnoughRepPointsException(_('mark posts as community wiki'))
+
+        WikifyAction(node=node, user=user, ip=request.META['REMOTE_ADDR']).save()
+
+    return RefreshPageCommand()
+
+@decorate.withfn(command)
+def convert_to_comment(request, id):
+    user = request.user
+    answer = get_object_or_404(Answer, id=id)
+    question = answer.question
+
+    if not request.POST:
+        description = lambda a: _("Answer by %(uname)s: %(snippet)s...") % {'uname': a.author.username,
+                                                                            'snippet': a.summary[:10]}
+        nodes = [(question.id, _("Question"))]
+        [nodes.append((a.id, description(a))) for a in
+         question.answers.filter_state(deleted=False).exclude(id=answer.id)]
+
+        return render_to_response('node/convert_to_comment.html', {'answer': answer, 'nodes': nodes})
+
+    if not user.is_authenticated():
+        raise AnonymousNotAllowedException(_("convert answers to comments"))
+
+    if not user.can_convert_to_comment(answer):
+        raise NotEnoughRepPointsException(_("convert answers to comments"))
+
+    try:
+        new_parent = Node.objects.get(id=request.POST.get('under', None))
+    except:
+        raise CommandException(_("That is an invalid post to put the comment under"))
+
+    if not (new_parent == question or (new_parent.node_type == 'answer' and new_parent.parent == question)):
+        raise CommandException(_("That is an invalid post to put the comment under"))
+
+    AnswerToCommentAction(user=user, node=answer, ip=request.META['REMOTE_ADDR']).save(data=dict(new_parent=new_parent))
+
+    return RefreshPageCommand()
+
+@decorate.withfn(command)
+def convert_comment_to_answer(request, id):
+    user = request.user
+    comment = get_object_or_404(Comment, id=id)
+    parent = comment.parent
+
+    if not parent.question:
+        question = parent
+    else:
+        question = parent.question
+    
+    if not user.is_authenticated():
+        raise AnonymousNotAllowedException(_("convert comments to answers"))
+
+    if not user.can_convert_comment_to_answer(comment):
+        raise NotEnoughRepPointsException(_("convert comments to answers"))
+    
+    CommentToAnswerAction(user=user, node=comment, ip=request.META['REMOTE_ADDR']).save(data=dict(question=question))
+
+    return RefreshPageCommand()
+
+@decorate.withfn(command)
+def convert_to_question(request, id):
+    user = request.user
+    answer = get_object_or_404(Answer, id=id)
+    question = answer.question
+
+    if not request.POST:
+        description = lambda a: _("Answer by %(uname)s: %(snippet)s...") % {'uname': a.author.username,
+                                                                            'snippet': a.summary[:10]}
+        nodes = [(question.id, _("Question"))]
+        [nodes.append((a.id, description(a))) for a in
+         question.answers.filter_state(deleted=False).exclude(id=answer.id)]
+
+        return render_to_response('node/convert_to_question.html', {'answer': answer})
+
+    if not user.is_authenticated():
+        raise AnonymousNotAllowedException(_("convert answers to questions"))
+
+    if not user.can_convert_to_question(answer):
+        raise NotEnoughRepPointsException(_("convert answers to questions"))
+
+    try:
+        title = request.POST.get('title', None)
+    except:
+        raise CommandException(_("You haven't specified the title of the new question"))
+
+    AnswerToQuestionAction(user=user, node=answer, ip=request.META['REMOTE_ADDR']).save(data=dict(title=title))
+
+    return RefreshPageCommand()
+
+@decorate.withfn(command)
+def subscribe(request, id, user=None):
+    if user:
+        try:
+            user = User.objects.get(id=user)
+        except User.DoesNotExist:
+            raise Http404()
+
+        if not (request.user.is_a_super_user_or_staff() or user.is_authenticated()):
+            raise CommandException(_("You do not have the correct credentials to preform this action."))
+    else:
+        user = request.user
+
+    question = get_object_or_404(Question, id=id)
+
+    try:
+        subscription = QuestionSubscription.objects.get(question=question, user=user)
+        subscription.delete()
+        subscribed = False
+    except:
+        subscription = QuestionSubscription(question=question, user=user, auto_subscription=False)
+        subscription.save()
+        subscribed = True
+
+    return {
+        'commands': {
+            'set_subscription_button': [subscribed and _('unsubscribe me') or _('subscribe me')],
+            'set_subscription_status': ['']
+        }
+    }
+
+#internally grouped views - used by the tagging system
+@ajax_login_required
+def mark_tag(request, tag=None, **kwargs):#tagging system
+    action = kwargs['action']
+    ts = MarkedTag.objects.filter(user=request.user, tag__name=tag)
+    if action == 'remove':
+        logging.debug('deleting tag %s' % tag)
+        ts.delete()
+    else:
+        reason = kwargs['reason']
+        if len(ts) == 0:
+            try:
+                t = Tag.objects.get(name=tag)
+                mt = MarkedTag(user=request.user, reason=reason, tag=t)
+                mt.save()
+            except:
+                pass
+        else:
+            ts.update(reason=reason)
+    return HttpResponse(simplejson.dumps(''), mimetype="application/json")
+
+def matching_tags(request):
+    if len(request.GET['q']) == 0:
+        raise CommandException(_("Invalid request"))
+
+    possible_tags = Tag.active.filter(name__icontains = request.GET['q'])
+    tag_output = ''
+    for tag in possible_tags:
+        tag_output += "%s|%s|%s\n" % (tag.id, tag.name, tag.used_count)
+
+    return HttpResponse(tag_output, mimetype="text/plain")
+
+def matching_users(request):
+    if len(request.GET['q']) == 0:
+        raise CommandException(_("Invalid request"))
+
+    possible_users = User.objects.filter(username__icontains = request.GET['q'])
+    output = ''
+
+    for user in possible_users:
+        output += ("%s|%s|%s\n" % (user.id, user.decorated_name, user.reputation))
+
+    return HttpResponse(output, mimetype="text/plain")
+
+def related_questions(request):
+    if request.POST and request.POST.get('title', None):
+        can_rank, questions = Question.objects.search(request.POST['title'])
+        return HttpResponse(simplejson.dumps(
+                [dict(title=q.title, url=q.get_absolute_url(), score=q.score, summary=q.summary)
+                 for q in questions.filter_state(deleted=False)[0:10]]), mimetype="application/json")
+    else:
+        raise Http404()
+
+
+
+
+
+
+
diff --git a/forum/modules/template_loader.py/forum/views/decorators.py b/forum/modules/template_loader.py/forum/views/decorators.py
new file mode 100644 (file)
index 0000000..20eb45c
--- /dev/null
@@ -0,0 +1,80 @@
+from django.http import HttpResponse, HttpResponseRedirect, Http404\r
+from django.utils import simplejson\r
+from django.core.paginator import Paginator, EmptyPage\r
+from django.shortcuts import render_to_response\r
+from django.core.urlresolvers import reverse\r
+from django.template import RequestContext\r
+from django.utils.translation import ungettext, ugettext as _\r
+from forum.modules import ui, decorate\r
+from datetime import datetime, date\r
+from forum.settings import ONLINE_USERS\r
+import logging\r
+\r
+def login_required(func, request, *args, **kwargs):\r
+    if not request.user.is_authenticated():\r
+        return HttpResponseRedirect(reverse('auth_signin'))\r
+    else:\r
+        return func(request, *args, **kwargs)\r
+\r
+def render(template=None, tab=None, tab_title='', weight=500, tabbed=True):\r
+    def decorator(func):        \r
+        def decorated(context, request, *args, **kwargs):\r
+            if request.user.is_authenticated():\r
+                ONLINE_USERS[request.user] = datetime.now()\r
+\r
+            if isinstance(context, HttpResponse):\r
+                return context\r
+\r
+            if tab is not None:\r
+                context['tab'] = tab\r
+\r
+            return render_to_response(context.pop('template', template), context,\r
+                                      context_instance=RequestContext(request))\r
+\r
+        if tabbed and tab and tab_title:\r
+            ui.register(ui.PAGE_TOP_TABS,\r
+                        ui.PageTab(tab, tab_title, lambda: reverse(func.__name__), weight=weight))\r
+            \r
+        return decorate.result.withfn(decorated, needs_params=True)(func)\r
+\r
+    return decorator\r
+\r
+class CommandException(Exception):\r
+    pass\r
+\r
+class RefreshPageCommand(HttpResponse):\r
+    def __init__(self):\r
+        super(RefreshPageCommand, self).__init__(\r
+                content=simplejson.dumps({'commands': {'refresh_page': []}, 'success': True}),\r
+                mimetype="application/json")\r
+\r
+def command(func, request, *args, **kwargs):\r
+    try:\r
+        response = func(request, *args, **kwargs)\r
+\r
+        if isinstance(response, HttpResponse):\r
+            return response\r
+\r
+        response['success'] = True\r
+    except Exception, e:\r
+        import traceback\r
+        #traceback.print_exc()\r
+\r
+        if isinstance(e, CommandException):\r
+            response = {\r
+            'success': False,\r
+            'error_message': e.message\r
+            }\r
+        else:\r
+            logging.error("%s: %s" % (func.__name__, str(e)))\r
+            logging.error(traceback.format_exc())\r
+            response = {\r
+            'success': False,\r
+            'error_message': _("We're sorry, but an unknown error ocurred.<br />Please try again in a while.")\r
+            }\r
+\r
+    if request.is_ajax():\r
+        return HttpResponse(simplejson.dumps(response), mimetype="application/json")\r
+    else:\r
+        return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))\r
+\r
diff --git a/forum/modules/template_loader.py/forum/views/meta.py b/forum/modules/template_loader.py/forum/views/meta.py
new file mode 100644 (file)
index 0000000..536cf26
--- /dev/null
@@ -0,0 +1,162 @@
+import os
+from itertools import groupby
+from django.shortcuts import render_to_response, get_object_or_404
+from django.core.urlresolvers import reverse
+from django.template import RequestContext, loader
+from django.http import HttpResponseRedirect, HttpResponse, Http404
+from django.views.static import serve
+from forum import settings
+from forum.modules import decorate
+from forum.views.decorators import login_required
+from forum.forms import FeedbackForm
+from django.core.urlresolvers import reverse
+from django.utils.translation import ugettext as _
+from django.db.models import Count
+from forum.forms import get_next_url
+from forum.models import Badge, Award, User, Page
+from forum.badges.base import BadgesMeta
+from forum import settings
+from forum.utils.mail import send_template_email
+from django.utils.safestring import mark_safe
+from forum.templatetags.extra_filters import or_preview
+import decorators
+import re
+
+def favicon(request):
+    return HttpResponseRedirect(str(settings.APP_FAVICON))
+
+def custom_css(request):
+    return HttpResponse(or_preview(settings.CUSTOM_CSS, request), mimetype="text/css")
+
+def static(request, title, content):
+    return render_to_response('static.html', {'content' : content, 'title': title},
+                              context_instance=RequestContext(request))
+
+def media(request, skin, path):
+    response = serve(request, "%s/media/%s" % (skin, path),
+                 document_root=os.path.join(os.path.dirname(os.path.dirname(__file__)), 'skins').replace('\\', '/'))
+    content_type = response['Content-Type']
+    if ('charset=' not in content_type):
+        if (content_type.startswith('text') or content_type=='application/x-javascript'):
+            content_type += '; charset=utf-8'
+            response['Content-Type'] = content_type
+    return response
+
+
+def markdown_help(request):
+    return render_to_response('markdown_help.html', context_instance=RequestContext(request))
+
+
+def opensearch(request):
+    return render_to_response('opensearch.html', {'settings' : settings}, context_instance=RequestContext(request))
+
+
+def feedback(request):
+    if request.method == "POST":
+        form = FeedbackForm(request.user, data=request.POST)
+        if form.is_valid():
+            context = {
+                 'user': request.user,
+                 'email': request.user.is_authenticated() and request.user.email or form.cleaned_data.get('email', None),
+                 'message': form.cleaned_data['message'],
+                 'name': request.user.is_authenticated() and request.user.username or form.cleaned_data.get('name', None),
+                 'ip': request.META['REMOTE_ADDR'],
+            }
+
+            recipients = User.objects.filter(is_superuser=True)
+            send_template_email(recipients, "notifications/feedback.html", context)
+
+            msg = _('Thanks for the feedback!')
+            request.user.message_set.create(message=msg)
+            return HttpResponseRedirect(get_next_url(request))
+    else:
+        form = FeedbackForm(request.user, initial={'next':get_next_url(request)})
+
+    return render_to_response('feedback.html', {'form': form}, context_instance=RequestContext(request))
+
+feedback.CANCEL_MESSAGE=_('We look forward to hearing your feedback! Please, give it next time :)')
+
+def privacy(request):
+    return render_to_response('privacy.html', context_instance=RequestContext(request))
+
+@decorate.withfn(login_required)
+def logout(request):
+    return render_to_response('logout.html', {
+    'next' : get_next_url(request),
+    }, context_instance=RequestContext(request))
+
+@decorators.render('badges.html', 'badges', _('badges'), weight=300)
+def badges(request):
+    badges = [b.ondb for b in sorted(BadgesMeta.by_id.values(), lambda b1, b2: cmp(b1.name, b2.name))]
+
+    if request.user.is_authenticated():
+        my_badges = Award.objects.filter(user=request.user).values('badge_id').distinct()
+    else:
+        my_badges = []
+
+    return {
+        'badges' : badges,
+        'mybadges' : my_badges,
+    }
+
+def badge(request, id, slug):
+    badge = Badge.objects.get(id=id)
+    awards = list(Award.objects.filter(badge=badge).order_by('user', 'awarded_at'))
+    award_count = len(awards)
+
+    awards = sorted([dict(count=len(list(g)), user=k) for k, g in groupby(awards, lambda a: a.user)],
+                    lambda c1, c2: c2['count'] - c1['count'])
+
+    return render_to_response('badge.html', {
+    'award_count': award_count,
+    'awards' : awards,
+    'badge' : badge,
+    }, context_instance=RequestContext(request))
+
+def page(request, path):
+    if path in settings.STATIC_PAGE_REGISTRY:
+        try:
+            page = Page.objects.get(id=settings.STATIC_PAGE_REGISTRY[path])
+
+            if (not page.published) and (not request.user.is_superuser):
+                raise Http404
+        except:
+            raise Http404
+    else:
+        raise Http404
+
+    template = page.extra.get('template', 'default')
+    sidebar = page.extra.get('sidebar', '')
+
+    if template == 'default':
+        base = 'base_content.html'
+    elif template == 'sidebar':
+        base = 'base.html'
+
+        sidebar_render = page.extra.get('render', 'markdown')
+
+        if sidebar_render == 'markdown':
+            sidebar = page._as_markdown(sidebar)
+        elif sidebar_render == 'html':
+            sidebar = mark_safe(sidebar)
+
+    else:
+        return HttpResponse(page.body, mimetype=page.extra.get('mimetype', 'text/html'))
+
+    render = page.extra.get('render', 'markdown')
+
+    if render == 'markdown':
+        body = page.as_markdown()
+    elif render == 'html':
+        body = mark_safe(page.body)
+    else:
+        body = page.body
+
+    return render_to_response('page.html', {
+    'page' : page,
+    'body' : body,
+    'sidebar': sidebar,
+    'base': base,
+    }, context_instance=RequestContext(request))
+
+
diff --git a/forum/modules/template_loader.py/forum/views/readers.py b/forum/modules/template_loader.py/forum/views/readers.py
new file mode 100644 (file)
index 0000000..80709e7
--- /dev/null
@@ -0,0 +1,374 @@
+# encoding:utf-8
+import datetime
+import logging
+from urllib import unquote
+from forum import settings as django_settings
+from django.shortcuts import render_to_response, get_object_or_404
+from django.http import HttpResponseRedirect, HttpResponse, Http404, HttpResponsePermanentRedirect
+from django.core.paginator import Paginator, EmptyPage, InvalidPage
+from django.template import RequestContext
+from django import template
+from django.utils.html import *
+from django.utils import simplejson
+from django.db.models import Q, Count
+from django.utils.translation import ugettext as _
+from django.template.defaultfilters import slugify
+from django.core.urlresolvers import reverse
+from django.utils.datastructures import SortedDict
+from django.views.decorators.cache import cache_page
+from django.utils.http import urlquote  as django_urlquote
+from django.template.defaultfilters import slugify
+from django.utils.safestring import mark_safe
+
+from forum.utils.html import sanitize_html, hyperlink
+from forum.utils.diff import textDiff as htmldiff
+from forum.utils import pagination
+from forum.forms import *
+from forum.models import *
+from forum.forms import get_next_url
+from forum.actions import QuestionViewAction
+from forum.http_responses import HttpResponseUnauthorized
+from forum.feed import RssQuestionFeed, RssAnswerFeed
+from forum.utils.pagination import generate_uri
+import decorators
+
+class HottestQuestionsSort(pagination.SortBase):
+    def apply(self, questions):
+        return questions.annotate(new_child_count=Count('all_children')).filter(
+                all_children__added_at__gt=datetime.datetime.now() - datetime.timedelta(days=1)).order_by('-new_child_count')
+
+
+class QuestionListPaginatorContext(pagination.PaginatorContext):
+    def __init__(self, id='QUESTIONS_LIST', prefix='', default_pagesize=30):
+        super (QuestionListPaginatorContext, self).__init__(id, sort_methods=(
+            (_('active'), pagination.SimpleSort(_('active'), '-last_activity_at', _("Most <strong>recently updated</strong> questions"))),
+            (_('newest'), pagination.SimpleSort(_('newest'), '-added_at', _("most <strong>recently asked</strong> questions"))),
+            (_('hottest'), HottestQuestionsSort(_('hottest'), _("most <strong>active</strong> questions in the last 24 hours</strong>"))),
+            (_('mostvoted'), pagination.SimpleSort(_('most voted'), '-score', _("most <strong>voted</strong> questions"))),
+        ), pagesizes=(15, 30, 50), default_pagesize=default_pagesize, prefix=prefix)
+
+class AnswerSort(pagination.SimpleSort):
+    def apply(self, answers):
+        if not settings.DISABLE_ACCEPTING_FEATURE:
+            return answers.order_by(*(['-marked'] + list(self._get_order_by())))
+        else:
+            return super(AnswerSort, self).apply(answers)
+
+class AnswerPaginatorContext(pagination.PaginatorContext):
+    def __init__(self, id='ANSWER_LIST', prefix='', default_pagesize=10):
+        super (AnswerPaginatorContext, self).__init__(id, sort_methods=(
+            (_('oldest'), AnswerSort(_('oldest answers'), 'added_at', _("oldest answers will be shown first"))),
+            (_('newest'), AnswerSort(_('newest answers'), '-added_at', _("newest answers will be shown first"))),
+            (_('votes'), AnswerSort(_('popular answers'), ('-score', 'added_at'), _("most voted answers will be shown first"))),
+        ), default_sort=_('votes'), pagesizes=(5, 10, 20), default_pagesize=default_pagesize, prefix=prefix)
+
+class TagPaginatorContext(pagination.PaginatorContext):
+    def __init__(self):
+        super (TagPaginatorContext, self).__init__('TAG_LIST', sort_methods=(
+            (_('name'), pagination.SimpleSort(_('by name'), 'name', _("sorted alphabetically"))),
+            (_('used'), pagination.SimpleSort(_('by popularity'), '-used_count', _("sorted by frequency of tag use"))),
+        ), default_sort=_('used'), pagesizes=(30, 60, 120))
+    
+
+def feed(request):
+    return RssQuestionFeed(
+                request,
+                Question.objects.filter_state(deleted=False).order_by('-last_activity_at'),
+                settings.APP_TITLE + _(' - ')+ _('latest questions'),
+                settings.APP_DESCRIPTION)(request)
+
+@decorators.render('index.html')
+def index(request):
+    paginator_context = QuestionListPaginatorContext()
+    paginator_context.base_path = reverse('questions')
+    return question_list(request,
+                         Question.objects.all(),
+                         base_path=reverse('questions'),
+                         feed_url=reverse('latest_questions_feed'),
+                         paginator_context=paginator_context)
+
+@decorators.render('questions.html', 'unanswered', _('unanswered'), weight=400)
+def unanswered(request):
+    return question_list(request,
+                         Question.objects.exclude(id__in=Question.objects.filter(children__marked=True).distinct()),
+                         _('open questions without an accepted answer'),
+                         None,
+                         _("Unanswered Questions"))
+
+@decorators.render('questions.html', 'questions', _('questions'), weight=0)
+def questions(request):
+    return question_list(request, Question.objects.all(), _('questions'))
+
+@decorators.render('questions.html')
+def tag(request, tag):
+    return question_list(request,
+                         Question.objects.filter(tags__name=unquote(tag)),
+                         mark_safe(_('questions tagged <span class="tag">%(tag)s</span>') % {'tag': tag}),
+                         None,
+                         mark_safe(_('Questions Tagged With %(tag)s') % {'tag': tag}),
+                         False)
+
+@decorators.render('questions.html', 'questions', tabbed=False)
+def user_questions(request, mode, user, slug):
+    user = get_object_or_404(User, id=user)
+
+    if mode == _('asked-by'):
+        questions = Question.objects.filter(author=user)
+        description = _("Questions asked by %s")
+    elif mode == _('answered-by'):
+        questions = Question.objects.filter(children__author=user, children__node_type='answer').distinct()
+        description = _("Questions answered by %s")
+    elif mode == _('subscribed-by'):
+        if not (request.user.is_superuser or request.user == user):
+            return HttpResponseUnauthorized(request)
+        questions = user.subscriptions
+
+        if request.user == user:
+            description = _("Questions you subscribed %s")
+        else:
+            description = _("Questions subscribed by %s")
+    else:
+        raise Http404
+
+
+    return question_list(request, questions,
+                         mark_safe(description % hyperlink(user.get_profile_url(), user.username)),
+                         page_title=description % user.username)
+
+def question_list(request, initial,
+                  list_description=_('questions'),
+                  base_path=None,
+                  page_title=_("All Questions"),
+                  allowIgnoreTags=True,
+                  feed_url=None,
+                  paginator_context=None):
+
+    questions = initial.filter_state(deleted=False)
+
+    if request.user.is_authenticated() and allowIgnoreTags:
+        questions = questions.filter(~Q(tags__id__in = request.user.marked_tags.filter(user_selections__reason = 'bad')))
+
+    if page_title is None:
+        page_title = _("Questions")
+
+    if request.GET.get('type', None) == 'rss':
+        questions = questions.order_by('-added_at')
+        return RssQuestionFeed(request, questions, page_title, list_description)(request)
+
+    keywords =  ""
+    if request.GET.get("q"):
+        keywords = request.GET.get("q").strip()
+
+    #answer_count = Answer.objects.filter_state(deleted=False).filter(parent__in=questions).count()
+    #answer_description = _("answers")
+
+    if not feed_url:
+        req_params = "&".join(generate_uri(request.GET, (_('page'), _('pagesize'), _('sort'))))
+        if req_params:
+            req_params = '&' + req_params
+
+        feed_url = mark_safe(escape(request.path + "?type=rss" + req_params))
+
+    return pagination.paginated(request, ('questions', paginator_context or QuestionListPaginatorContext()), {
+    "questions" : questions.distinct(),
+    "questions_count" : questions.count(),
+    "keywords" : keywords,
+    "list_description": list_description,
+    "base_path" : base_path,
+    "page_title" : page_title,
+    "tab" : "questions",
+    'feed_url': feed_url,
+    })
+
+
+def search(request):
+    if request.method == "GET" and "q" in request.GET:
+        keywords = request.GET.get("q")
+        search_type = request.GET.get("t")
+
+        if not keywords:
+            return HttpResponseRedirect(reverse(index))
+        if search_type == 'tag':
+            return HttpResponseRedirect(reverse('tags') + '?q=%s' % urlquote(keywords.strip()))
+        elif search_type == "user":
+            return HttpResponseRedirect(reverse('users') + '?q=%s' % urlquote(keywords.strip()))
+        else:
+            return question_search(request, keywords)
+    else:
+        return render_to_response("search.html", context_instance=RequestContext(request))
+
+@decorators.render('questions.html')
+def question_search(request, keywords):
+    can_rank, initial = Question.objects.search(keywords)
+
+    if can_rank:
+        paginator_context = QuestionListPaginatorContext()
+        paginator_context.sort_methods[_('ranking')] = pagination.SimpleSort(_('relevance'), '-ranking', _("most relevant questions"))
+        paginator_context.force_sort = _('ranking')
+    else:
+        paginator_context = None
+
+    return question_list(request, initial,
+                         _("questions matching '%(keywords)s'") % {'keywords': keywords},
+                         None,
+                         _("questions matching '%(keywords)s'") % {'keywords': keywords},
+                         paginator_context=paginator_context)
+
+
+@decorators.render('tags.html', 'tags', _('tags'), weight=100)
+def tags(request):
+    stag = ""
+    tags = Tag.active.all()
+
+    if request.method == "GET":
+        stag = request.GET.get("q", "").strip()
+        if stag:
+            tags = tags.filter(name__icontains=stag)
+
+    return pagination.paginated(request, ('tags', TagPaginatorContext()), {
+        "tags" : tags,
+        "stag" : stag,
+        "keywords" : stag
+    })
+
+def update_question_view_times(request, question):
+    if not 'last_seen_in_question' in request.session:
+        request.session['last_seen_in_question'] = {}
+
+    last_seen = request.session['last_seen_in_question'].get(question.id, None)
+
+    if (not last_seen) or last_seen < question.last_activity_at:
+        QuestionViewAction(question, request.user, ip=request.META['REMOTE_ADDR']).save()
+        request.session['last_seen_in_question'][question.id] = datetime.datetime.now()
+
+    request.session['last_seen_in_question'][question.id] = datetime.datetime.now()
+
+def match_question_slug(id, slug):
+    slug_words = slug.split('-')
+    qs = Question.objects.filter(title__istartswith=slug_words[0])
+
+    for q in qs:
+        if slug == urlquote(slugify(q.title)):
+            return q
+
+    return None
+
+def answer_redirect(request, answer):
+    pc = AnswerPaginatorContext()
+
+    sort = pc.sort(request)
+
+    if sort == _('oldest'):
+        filter = Q(added_at__lt=answer.added_at)
+    elif sort == _('newest'):
+        filter = Q(added_at__gt=answer.added_at)
+    elif sort == _('votes'):
+        filter = Q(score__gt=answer.score) | Q(score=answer.score, added_at__lt=answer.added_at)
+    else:
+        raise Http404()
+
+    count = answer.question.answers.filter(Q(marked=True) | filter).exclude(state_string="(deleted)").count()
+    pagesize = pc.pagesize(request)
+
+    page = count / pagesize
+    
+    if count % pagesize:
+        page += 1
+        
+    if page == 0:
+        page = 1
+
+    return HttpResponsePermanentRedirect("%s?%s=%s#%s" % (
+        answer.question.get_absolute_url(), _('page'), page, answer.id))
+
+@decorators.render("question.html", 'questions')
+def question(request, id, slug='', answer=None):
+    try:
+        question = Question.objects.get(id=id)
+    except:
+        if slug:
+            question = match_question_slug(id, slug)
+            if question is not None:
+                return HttpResponseRedirect(question.get_absolute_url())
+
+        raise Http404()
+
+    if question.nis.deleted and not request.user.can_view_deleted_post(question):
+        raise Http404
+
+    if request.GET.get('type', None) == 'rss':
+        return RssAnswerFeed(request, question, include_comments=request.GET.get('comments', None) == 'yes')(request)
+
+    if answer:
+        answer = get_object_or_404(Answer, id=answer)
+
+        if (question.nis.deleted and not request.user.can_view_deleted_post(question)) or answer.question != question:
+            raise Http404
+
+        if answer.marked:
+            return HttpResponsePermanentRedirect(question.get_absolute_url())
+
+        return answer_redirect(request, answer)
+
+    if settings.FORCE_SINGLE_URL and (slug != slugify(question.title)):
+        return HttpResponsePermanentRedirect(question.get_absolute_url())
+
+    if request.POST:
+        answer_form = AnswerForm(request.POST, user=request.user)
+    else:
+        answer_form = AnswerForm(user=request.user)
+
+    answers = request.user.get_visible_answers(question)
+
+    update_question_view_times(request, question)
+
+    if request.user.is_authenticated():
+        try:
+            subscription = QuestionSubscription.objects.get(question=question, user=request.user)
+        except:
+            subscription = False
+    else:
+        subscription = False
+
+    return pagination.paginated(request, ('answers', AnswerPaginatorContext()), {
+    "question" : question,
+    "answer" : answer_form,
+    "answers" : answers,
+    "similar_questions" : question.get_related_questions(),
+    "subscription": subscription,
+    })
+
+
+REVISION_TEMPLATE = template.loader.get_template('node/revision.html')
+
+def revisions(request, id):
+    post = get_object_or_404(Node, id=id).leaf
+    revisions = list(post.revisions.order_by('revised_at'))
+    rev_ctx = []
+
+    for i, revision in enumerate(revisions):
+        rev_ctx.append(dict(inst=revision, html=template.loader.get_template('node/revision.html').render(template.Context({
+        'title': revision.title,
+        'html': revision.html,
+        'tags': revision.tagname_list(),
+        }))))
+
+        if i > 0:
+            rev_ctx[i]['diff'] = mark_safe(htmldiff(rev_ctx[i-1]['html'], rev_ctx[i]['html']))
+        else:
+            rev_ctx[i]['diff'] = mark_safe(rev_ctx[i]['html'])
+
+        if not (revision.summary):
+            rev_ctx[i]['summary'] = _('Revision n. %(rev_number)d') % {'rev_number': revision.revision}
+        else:
+            rev_ctx[i]['summary'] = revision.summary
+
+    rev_ctx.reverse()
+
+    return render_to_response('revisions.html', {
+    'post': post,
+    'revisions': rev_ctx,
+    }, context_instance=RequestContext(request))
+
+
+
diff --git a/forum/modules/template_loader.py/forum/views/users.py b/forum/modules/template_loader.py/forum/views/users.py
new file mode 100644 (file)
index 0000000..50c295f
--- /dev/null
@@ -0,0 +1,454 @@
+from forum.models import User\r
+from django.db.models import Q, Count\r
+from django.core.paginator import Paginator, EmptyPage, InvalidPage\r
+from django.template.defaultfilters import slugify\r
+from django.contrib.contenttypes.models import ContentType\r
+from django.core.urlresolvers import reverse\r
+from django.shortcuts import render_to_response, get_object_or_404\r
+from django.template import RequestContext\r
+from django.http import HttpResponse, HttpResponseRedirect, Http404\r
+from forum.http_responses import HttpResponseUnauthorized\r
+from django.utils.translation import ugettext as _\r
+from django.utils.http import urlquote_plus\r
+from django.utils.html import strip_tags\r
+from django.utils import simplejson\r
+from django.core.urlresolvers import reverse, NoReverseMatch\r
+from forum.forms import *\r
+from forum.utils.html import sanitize_html\r
+from forum.modules import decorate, ReturnImediatelyException\r
+from datetime import datetime, date\r
+from forum.actions import EditProfileAction, FavoriteAction, BonusRepAction, SuspendAction\r
+from forum.modules import ui\r
+from forum.utils import pagination\r
+from forum.views.readers import QuestionListPaginatorContext, AnswerPaginatorContext\r
+from forum.settings import ONLINE_USERS\r
\r
+import bisect\r
+import time\r
+import datetime\r
+import decorators\r
+import unicodedata\r
+\r
+class UserReputationSort(pagination.SimpleSort):\r
+    def apply(self, objects):\r
+        return objects.order_by('-is_active', self.order_by)\r
+\r
+class UserListPaginatorContext(pagination.PaginatorContext):\r
+    def __init__(self):\r
+        super (UserListPaginatorContext, self).__init__('USERS_LIST', sort_methods=(\r
+            (_('reputation'), UserReputationSort(_('reputation'), '-reputation', _("sorted by reputation"))),\r
+            (_('newest'), pagination.SimpleSort(_('recent'), '-date_joined', _("newest members"))),\r
+            (_('last'), pagination.SimpleSort(_('oldest'), 'date_joined', _("oldest members"))),\r
+            (_('name'), pagination.SimpleSort(_('by username'), 'username', _("sorted by username"))),\r
+        ), pagesizes=(20, 35, 60))\r
+\r
+class SubscriptionListPaginatorContext(pagination.PaginatorContext):\r
+    def __init__(self):\r
+        super (SubscriptionListPaginatorContext, self).__init__('SUBSCRIPTION_LIST', pagesizes=(5, 10, 20), default_pagesize=20)\r
+\r
+class UserAnswersPaginatorContext(pagination.PaginatorContext):\r
+    def __init__(self):\r
+        super (UserAnswersPaginatorContext, self).__init__('USER_ANSWER_LIST', sort_methods=(\r
+            (_('oldest'), pagination.SimpleSort(_('oldest answers'), 'added_at', _("oldest answers will be shown first"))),\r
+            (_('newest'), pagination.SimpleSort(_('newest answers'), '-added_at', _("newest answers will be shown first"))),\r
+            (_('votes'), pagination.SimpleSort(_('popular answers'), '-score', _("most voted answers will be shown first"))),\r
+        ), default_sort=_('votes'), pagesizes=(5, 10, 20), default_pagesize=20, prefix=_('answers'))\r
+\r
+USERS_PAGE_SIZE = 35# refactor - move to some constants file\r
+\r
+@decorators.render('users/users.html', 'users', _('users'), weight=200)\r
+def users(request):\r
+    suser = request.REQUEST.get('q', "")\r
+    users = User.objects.all()\r
+\r
+    if suser != "":\r
+        users = users.filter(username__icontains=suser)\r
+\r
+    return pagination.paginated(request, ('users', UserListPaginatorContext()), {\r
+        "users" : users,\r
+        "suser" : suser,\r
+    })\r
+\r
+\r
+@decorators.render('users/online_users.html', 'online_users', _('Online Users'), weight=200, tabbed=False)\r
+def online_users(request):\r
+    suser = request.REQUEST.get('q', "")\r
+\r
+    sort = ""\r
+    if request.GET.get("sort", None):\r
+        try:\r
+            sort = int(request.GET["sort"])\r
+        except ValueError:\r
+            logging.error('Found invalid sort "%s", loading %s, refered by %s' % (\r
+                request.GET.get("sort", ''), request.path, request.META.get('HTTP_REFERER', 'UNKNOWN')\r
+            ))\r
+            raise Http404()\r
+\r
+    page = 0\r
+    if request.GET.get("page", None):\r
+        try:\r
+            page = int(request.GET["page"])\r
+        except ValueError:\r
+            logging.error('Found invalid page "%s", loading %s, refered by %s' % (\r
+                request.GET.get("page", ''), request.path, request.META.get('HTTP_REFERER', 'UNKNOWN')\r
+            ))\r
+            raise Http404()\r
+\r
+    pagesize = 10\r
+    if request.GET.get("pagesize", None):\r
+        try:\r
+            pagesize = int(request.GET["pagesize"])\r
+        except ValueError:\r
+            logging.error('Found invalid pagesize "%s", loading %s, refered by %s' % (\r
+                request.GET.get("pagesize", ''), request.path, request.META.get('HTTP_REFERER', 'UNKNOWN')\r
+            ))\r
+            raise Http404()\r
+\r
+\r
+    users = None\r
+    if sort == "reputation":\r
+        users = sorted(ONLINE_USERS.sets.keys(), key=lambda user: user.reputation)\r
+    elif sort == "newest" :\r
+        users = sorted(ONLINE_USERS.sets.keys(), key=lambda user: user.newest)\r
+    elif sort == "last":\r
+        users = sorted(ONLINE_USERS.sets.keys(), key=lambda user: user.last)\r
+    elif sort == "name":\r
+        users = sorted(ONLINE_USERS.sets.keys(), key=lambda user: user.name)\r
+    elif sort == "oldest":\r
+        users = sorted(ONLINE_USERS.sets.keys(), key=lambda user: user.oldest)\r
+    elif sort == "newest":\r
+        users = sorted(ONLINE_USERS.sets.keys(), key=lambda user: user.newest)\r
+    elif sort == "votes":\r
+        users = sorted(ONLINE_USERS.sets.keys(), key=lambda user: user.votes)\r
+    else:\r
+        users = sorted(ONLINE_USERS.iteritems(), key=lambda x: x[1])\r
+\r
+    return render_to_response('users/online_users.html', {\r
+        "users" : users,\r
+        "suser" : suser,\r
+        "sort" : sort,\r
+        "page" : page,\r
+        "pageSize" : pagesize,\r
+    })\r
+\r
+\r
+def edit_user(request, id):\r
+    user = get_object_or_404(User, id=id)\r
+    if not (request.user.is_superuser or request.user == user):\r
+        return HttpResponseUnauthorized(request)\r
+    if request.method == "POST":\r
+        form = EditUserForm(user, request.POST)\r
+        if form.is_valid():\r
+            new_email = sanitize_html(form.cleaned_data['email'])\r
+\r
+            if new_email != user.email:\r
+                user.email = new_email\r
+                user.email_isvalid = False\r
+\r
+                try:\r
+                    hash = ValidationHash.objects.get(user=request.user, type='email')\r
+                    hash.delete()\r
+                except:\r
+                    pass\r
+\r
+            if settings.EDITABLE_SCREEN_NAME:\r
+                user.username = sanitize_html(form.cleaned_data['username'])\r
+            user.real_name = sanitize_html(form.cleaned_data['realname'])\r
+            user.website = sanitize_html(form.cleaned_data['website'])\r
+            user.location = sanitize_html(form.cleaned_data['city'])\r
+            user.date_of_birth = form.cleaned_data['birthday']\r
+            if user.date_of_birth == "None":\r
+                user.date_of_birth = datetime(1900, 1, 1, 0, 0)\r
+            user.about = sanitize_html(form.cleaned_data['about'])\r
+\r
+            user.save()\r
+            EditProfileAction(user=user, ip=request.META['REMOTE_ADDR']).save()\r
+\r
+            request.user.message_set.create(message=_("Profile updated."))\r
+            return HttpResponseRedirect(user.get_profile_url())\r
+    else:\r
+        form = EditUserForm(user)\r
+    return render_to_response('users/edit.html', {\r
+    'user': user,\r
+    'form' : form,\r
+    'gravatar_faq_url' : reverse('faq') + '#gravatar',\r
+    }, context_instance=RequestContext(request))\r
+\r
+\r
+@decorate.withfn(decorators.command)\r
+def user_powers(request, id, action, status):\r
+    if not request.user.is_superuser:\r
+        raise decorators.CommandException(_("Only superusers are allowed to alter other users permissions."))\r
+\r
+    if (action == 'remove' and 'status' == 'super') and not request.user.is_siteowner():\r
+        raise decorators.CommandException(_("Only the site owner can remove the super user status from other user."))\r
+\r
+    user = get_object_or_404(User, id=id)\r
+    new_state = action == 'grant'\r
+\r
+    if status == 'super':\r
+        user.is_superuser = new_state\r
+    elif status == 'staff':\r
+        user.is_staff = new_state\r
+    else:\r
+        raise Http404()\r
+\r
+    user.save()\r
+    return decorators.RefreshPageCommand()\r
+\r
+\r
+@decorate.withfn(decorators.command)\r
+def award_points(request, id):\r
+    if not request.POST:\r
+        return render_to_response('users/karma_bonus.html')\r
+\r
+    if not request.user.is_superuser:\r
+        raise decorators.CommandException(_("Only superusers are allowed to award reputation points"))\r
+\r
+    try:\r
+        points = int(request.POST['points'])\r
+    except:\r
+        raise decorators.CommandException(_("Invalid number of points to award."))\r
+\r
+    user = get_object_or_404(User, id=id)\r
+\r
+    extra = dict(message=request.POST.get('message', ''), awarding_user=request.user.id, value=points)\r
+\r
+    BonusRepAction(user=request.user, extra=extra).save(data=dict(value=points, affected=user))\r
+\r
+    return {'commands': {\r
+            'update_profile_karma': [user.reputation]\r
+        }}\r
+    \r
+\r
+@decorate.withfn(decorators.command)\r
+def suspend(request, id):\r
+    user = get_object_or_404(User, id=id)\r
+\r
+    if not request.user.is_superuser:\r
+        raise decorators.CommandException(_("Only superusers can suspend other users"))\r
+\r
+    if not request.POST.get('bantype', None):\r
+        if user.is_suspended():\r
+            suspension = user.suspension\r
+            suspension.cancel(user=request.user, ip=request.META['REMOTE_ADDR'])\r
+            return decorators.RefreshPageCommand()\r
+        else:\r
+            return render_to_response('users/suspend_user.html')\r
+\r
+    data = {\r
+        'bantype': request.POST.get('bantype', 'indefinetly').strip(),\r
+        'publicmsg': request.POST.get('publicmsg', _('Bad behaviour')),\r
+        'privatemsg': request.POST.get('privatemsg', None) or request.POST.get('publicmsg', ''),\r
+        'suspended': user\r
+    }\r
+\r
+    if data['bantype'] == 'forxdays':\r
+        try:\r
+            data['forxdays'] = int(request.POST['forxdays'])\r
+        except:\r
+            raise decorators.CommandException(_('Invalid numeric argument for the number of days.'))\r
+\r
+    SuspendAction(user=request.user, ip=request.META['REMOTE_ADDR']).save(data=data)\r
+\r
+    return decorators.RefreshPageCommand()\r
+\r
+\r
+def user_view(template, tab_name, tab_title, tab_description, private=False, tabbed=True, render_to=None, weight=500):\r
+    def decorator(fn):\r
+        def params(request, id, slug=None):\r
+            user = get_object_or_404(User, id=id)\r
+            if private and not (user == request.user or request.user.is_superuser):\r
+                raise ReturnImediatelyException(HttpResponseUnauthorized(request))\r
+\r
+            if render_to and (not render_to(user)):\r
+                raise ReturnImediatelyException(HttpResponseRedirect(user.get_profile_url()))\r
+\r
+            return [request, user], {}\r
+\r
+        decorated = decorate.params.withfn(params)(fn)\r
+\r
+        def result(context, request, user):\r
+            rev_page_title = user.username + " - " + tab_description\r
+\r
+            context.update({\r
+                "tab": "users",\r
+                "active_tab" : tab_name,\r
+                "tab_description" : tab_description,\r
+                "page_title" : rev_page_title,\r
+                "can_view_private": (user == request.user) or request.user.is_superuser\r
+            })\r
+            return render_to_response(template, context, context_instance=RequestContext(request))\r
+\r
+        decorated = decorate.result.withfn(result, needs_params=True)(decorated)\r
+\r
+        if tabbed:\r
+            def url_getter(vu):\r
+                try:\r
+                    return reverse(fn.__name__, kwargs={'id': vu.id, 'slug': slugify(vu.username)})\r
+                except NoReverseMatch:\r
+                    return reverse(fn.__name__, kwargs={'id': vu.id})\r
+\r
+            ui.register(ui.PROFILE_TABS, ui.ProfileTab(\r
+                tab_name, tab_title, tab_description,url_getter, private, render_to, weight\r
+            ))\r
+\r
+        return decorated\r
+    return decorator\r
+\r
+\r
+@user_view('users/stats.html', 'stats', _('overview'), _('user overview'))\r
+def user_profile(request, user):\r
+    questions = Question.objects.filter_state(deleted=False).filter(author=user).order_by('-added_at')\r
+    answers = Answer.objects.filter_state(deleted=False).filter(author=user).order_by('-added_at')\r
+\r
+    up_votes = user.vote_up_count\r
+    down_votes = user.vote_down_count\r
+    votes_today = user.get_vote_count_today()\r
+    votes_total = int(settings.MAX_VOTES_PER_DAY)\r
+\r
+    user_tags = Tag.objects.filter(Q(nodes__author=user) | Q(nodes__children__author=user)) \\r
+        .annotate(user_tag_usage_count=Count('name')).order_by('-user_tag_usage_count')\r
+\r
+    awards = [(Badge.objects.get(id=b['id']), b['count']) for b in\r
+              Badge.objects.filter(awards__user=user).values('id').annotate(count=Count('cls')).order_by('-count')]\r
+\r
+    return pagination.paginated(request, (\r
+    ('questions', QuestionListPaginatorContext('USER_QUESTION_LIST', _('questions'), 15)),\r
+    ('answers', UserAnswersPaginatorContext())), {\r
+    "view_user" : user,\r
+    "questions" : questions,\r
+    "answers" : answers,\r
+    "up_votes" : up_votes,\r
+    "down_votes" : down_votes,\r
+    "total_votes": up_votes + down_votes,\r
+    "votes_today_left": votes_total-votes_today,\r
+    "votes_total_per_day": votes_total,\r
+    "user_tags" : user_tags[:50],\r
+    "awards": awards,\r
+    "total_awards" : len(awards),\r
+    })\r
+    \r
+@user_view('users/recent.html', 'recent', _('recent activity'), _('recent user activity'))\r
+def user_recent(request, user):\r
+    activities = user.actions.exclude(\r
+            action_type__in=("voteup", "votedown", "voteupcomment", "flag", "newpage", "editpage")).order_by(\r
+            '-action_date')[:USERS_PAGE_SIZE]\r
+\r
+    return {"view_user" : user, "activities" : activities}\r
+\r
+\r
+@user_view('users/reputation.html', 'reputation', _('reputation history'), _('graph of user karma'))\r
+def user_reputation(request, user):\r
+    rep = list(user.reputes.order_by('date'))\r
+    values = [r.value for r in rep]\r
+    redux = lambda x, y: x+y\r
+\r
+    graph_data = simplejson.dumps([\r
+    (time.mktime(rep[i].date.timetuple()) * 1000, reduce(redux, values[:i], 0))\r
+    for i in range(len(values))\r
+    ])\r
+\r
+    rep = user.reputes.filter(action__canceled=False).order_by('-date')[0:20]\r
+\r
+    return {"view_user": user, "reputation": rep, "graph_data": graph_data}\r
+\r
+@user_view('users/votes.html', 'votes', _('votes'), _('user vote record'), True)\r
+def user_votes(request, user):\r
+    votes = user.votes.exclude(node__state_string__contains="(deleted").filter(\r
+            node__node_type__in=("question", "answer")).order_by('-voted_at')[:USERS_PAGE_SIZE]\r
+\r
+    return {"view_user" : user, "votes" : votes}\r
+\r
+@user_view('users/questions.html', 'favorites', _('favorites'), _('questions that user selected as his/her favorite'))\r
+def user_favorites(request, user):\r
+    favorites = FavoriteAction.objects.filter(canceled=False, user=user)\r
+\r
+    return {"favorites" : favorites, "view_user" : user}\r
+\r
+@user_view('users/subscriptions.html', 'subscriptions', _('subscription'), _('subscriptions'), True, tabbed=False)\r
+def user_subscriptions(request, user):\r
+    enabled = user.subscription_settings.enable_notifications\r
+\r
+    tab = request.GET.get('tab', "settings")\r
+\r
+    if tab == 'settings':\r
+        manage_open = False\r
+        if request.method == 'POST':\r
+            manage_open = False\r
+            form = SubscriptionSettingsForm(data=request.POST, instance=user.subscription_settings)\r
+\r
+            if form.is_valid():\r
+                form.save()\r
+                message = _('New subscription settings are now saved')\r
+\r
+                if 'notswitch' in request.POST:\r
+                    enabled = not enabled\r
+\r
+                    if enabled:\r
+                        message = _('Notifications are now enabled')\r
+                    else:\r
+                        message = _('Notifications are now disabled')\r
+\r
+                user.subscription_settings.enable_notifications = enabled\r
+                user.subscription_settings.save()\r
+\r
+                request.user.message_set.create(message=message)\r
+        else:\r
+            form = SubscriptionSettingsForm(instance=user.subscription_settings)\r
+\r
+        return {\r
+            'view_user':user,\r
+            'notificatons_on': enabled,\r
+            'form':form,\r
+            'manage_open':manage_open,\r
+        }\r
+\r
+    elif tab == 'manage':\r
+        manage_open = True\r
+\r
+        auto = request.GET.get('auto', 'True')\r
+        if auto == 'True':\r
+            show_auto = True\r
+            subscriptions = QuestionSubscription.objects.filter(user=user).order_by('-last_view')\r
+        else:\r
+            show_auto = False\r
+            subscriptions = QuestionSubscription.objects.filter(user=user, auto_subscription=False).order_by('-last_view')\r
+\r
+        return pagination.paginated(request, ('subscriptions', SubscriptionListPaginatorContext()), {\r
+            'subscriptions':subscriptions,\r
+            'view_user':user,\r
+            "auto":show_auto,\r
+            'manage_open':manage_open,\r
+        })\r
+\r
+    # else:\r
+        # todo: probably want to throw an error\r
+        # error = "error to throw"\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+@user_view('users/preferences.html', 'preferences', _('preferences'), _('preferences'), True, tabbed=False)\r
+def user_preferences(request, user):\r
+    if request.POST:\r
+        form = UserPreferencesForm(request.POST)\r
+\r
+        if form.is_valid():\r
+            user.prop.preferences = form.cleaned_data\r
+            request.user.message_set.create(message=_('New preferences saved'))\r
+\r
+    else:\r
+        preferences = user.prop.preferences\r
+\r
+        if preferences:\r
+            form = UserPreferencesForm(initial=preferences)\r
+        else:\r
+            form = UserPreferencesForm()\r
+            \r
+    return {'view_user': user, 'form': form}\r
+\r
+\r
diff --git a/forum/modules/template_loader.py/forum/views/writers.py b/forum/modules/template_loader.py/forum/views/writers.py
new file mode 100644 (file)
index 0000000..dbc68c0
--- /dev/null
@@ -0,0 +1,270 @@
+# encoding:utf-8
+import os.path
+import time, datetime, random
+import logging
+from django.core.files.storage import FileSystemStorage
+from django.shortcuts import render_to_response, get_object_or_404
+from django.http import HttpResponseRedirect, HttpResponse, Http404
+from django.template import RequestContext
+from django.utils.html import *
+from django.utils import simplejson
+from django.utils.translation import ugettext as _
+from django.core.urlresolvers import reverse
+from django.core.exceptions import PermissionDenied
+
+from forum.actions import AskAction, AnswerAction, ReviseAction, RollbackAction, RetagAction
+from forum.forms import *
+from forum.models import *
+from forum.forms import get_next_url
+from forum.utils import html
+
+
+def upload(request):#ajax upload file to a question or answer
+    class FileTypeNotAllow(Exception):
+        pass
+    class FileSizeNotAllow(Exception):
+        pass
+    class UploadPermissionNotAuthorized(Exception):
+        pass
+
+    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 request.user.can_upload_files():
+            raise UploadPermissionNotAuthorized()
+
+        # check file type
+        try:
+            file_name_suffix = os.path.splitext(f.name)[1].lower()
+        except KeyError:
+            raise FileTypeNotAllow()
+
+        if not file_name_suffix in ('.jpg', '.jpeg', '.gif', '.png', '.bmp', '.tiff', '.ico'):
+            raise FileTypeNotAllow()
+
+        storage = FileSystemStorage(str(settings.UPFILES_FOLDER), str(settings.UPFILES_ALIAS))
+        new_file_name = storage.save("_".join(f.name.split()), f)
+        # check file size
+        # byte
+        size = storage.size(new_file_name)
+
+        if size > float(settings.ALLOW_MAX_FILE_SIZE) * 1024 * 1024:
+            storage.delete(new_file_name)
+            raise FileSizeNotAllow()
+
+        result = xml_template % ('Good', '', str(settings.UPFILES_ALIAS) + 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 %sM") % settings.ALLOW_MAX_FILE_SIZE, '')
+    except Exception, e:
+        result = xml_template % ('', _('Error uploading file. Please contact the site administrator. Thank you. %s' % e), '')
+
+    return HttpResponse(result, mimetype="application/xml")
+
+def ask(request):
+    form = None
+
+    if request.POST:
+        if request.session.pop('reviewing_pending_data', False):
+            form = AskForm(initial=request.POST, user=request.user)
+        elif "text" in request.POST:
+            form = AskForm(request.POST, user=request.user)
+            if form.is_valid():
+                if request.user.is_authenticated() and request.user.email_valid_and_can_ask():
+                    ask_action = AskAction(user=request.user, ip=request.META['REMOTE_ADDR']).save(data=form.cleaned_data)
+                    question = ask_action.node
+
+                    if settings.WIKI_ON and request.POST.get('wiki', False):
+                        question.nstate.wiki = ask_action
+
+                    return HttpResponseRedirect(question.get_absolute_url())
+                else:
+                    request.session['pending_submission_data'] = {
+                        'POST': request.POST,
+                        'data_name': _("question"),
+                        'type': 'ask',
+                        'submission_url': reverse('ask'),
+                        'time': datetime.datetime.now()
+                    }
+
+                    if request.user.is_authenticated():
+                        request.user.message_set.create(message=_("Your question is pending until you %s.") % html.hyperlink(
+                            reverse('send_validation_email'), _("validate your email")
+                        ))
+                        return HttpResponseRedirect(reverse('index'))
+                    else:
+                        return HttpResponseRedirect(reverse('auth_signin'))
+        elif "go" in request.POST:
+            form = AskForm({'title': request.POST['q']}, user=request.user)
+            
+    if not form:
+        form = AskForm(user=request.user)
+
+    return render_to_response('ask.html', {
+        'form' : form,
+        'tab' : 'ask'
+        }, context_instance=RequestContext(request))
+
+def edit_question(request, id):
+    question = get_object_or_404(Question, id=id)
+    if question.nis.deleted and not request.user.can_view_deleted_post(question):
+        raise Http404
+    if request.user.can_edit_post(question):
+        return _edit_question(request, question)
+    elif request.user.can_retag_questions():
+        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():
+                RetagAction(user=request.user, node=question, ip=request.META['REMOTE_ADDR']).save(data=dict(tagnames=form.cleaned_data['tags']))
+
+            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):
+    if request.method == 'POST':
+        revision_form = RevisionForm(question, data=request.POST)
+        revision_form.is_valid()
+        revision = question.revisions.get(revision=revision_form.cleaned_data['revision'])
+
+        if 'select_revision' in request.POST:
+            form = EditQuestionForm(question, request.user, revision)
+        else:
+            form = EditQuestionForm(question, request.user, revision, data=request.POST)
+
+        if not 'select_revision' in request.POST and form.is_valid():
+            if form.has_changed():
+                action = ReviseAction(user=request.user, node=question, ip=request.META['REMOTE_ADDR']).save(data=form.cleaned_data)
+
+                if settings.WIKI_ON:
+                    if request.POST.get('wiki', False) and not question.nis.wiki:
+                        question.nstate.wiki = action
+                    elif question.nis.wiki and (not request.POST.get('wiki', False)) and request.user.can_cancel_wiki(question):
+                        question.nstate.wiki = None
+            else:
+                if not revision == question.active_revision:
+                    RollbackAction(user=request.user, node=question).save(data=dict(activate=revision))
+
+            return HttpResponseRedirect(question.get_absolute_url())
+    else:
+        revision_form = RevisionForm(question)
+        form = EditQuestionForm(question, request.user)
+
+    return render_to_response('question_edit.html', {
+        'question': question,
+        'revision_form': revision_form,
+        'form' : form,
+        #'tags' : _get_tags_cache_json()
+    }, context_instance=RequestContext(request))
+
+def edit_answer(request, id):
+    answer = get_object_or_404(Answer, id=id)
+    if answer.deleted and not request.user.can_view_deleted_post(answer):
+        raise Http404
+    elif not request.user.can_edit_post(answer):
+        raise Http404
+
+    if request.method == "POST":
+        revision_form = RevisionForm(answer, data=request.POST)
+        revision_form.is_valid()
+        revision = answer.revisions.get(revision=revision_form.cleaned_data['revision'])
+
+        if 'select_revision' in request.POST:
+            form = EditAnswerForm(answer, request.user, revision)
+        else:
+            form = EditAnswerForm(answer, request.user, revision, data=request.POST)
+
+        if not 'select_revision' in request.POST and form.is_valid():
+            if form.has_changed():
+                action = ReviseAction(user=request.user, node=answer, ip=request.META['REMOTE_ADDR']).save(data=form.cleaned_data)
+
+                if settings.WIKI_ON:
+                    if request.POST.get('wiki', False) and not answer.nis.wiki:
+                        answer.nstate.wiki = action
+                    elif answer.nis.wiki and (not request.POST.get('wiki', False)) and request.user.can_cancel_wiki(answer):
+                        answer.nstate.wiki = None
+            else:
+                if not revision == answer.active_revision:
+                    RollbackAction(user=request.user, node=answer, ip=request.META['REMOTE_ADDR']).save(data=dict(activate=revision))
+
+            return HttpResponseRedirect(answer.get_absolute_url())
+
+    else:
+        revision_form = RevisionForm(answer)
+        form = EditAnswerForm(answer, request.user)
+    return render_to_response('answer_edit.html', {
+                              'answer': answer,
+                              'revision_form': revision_form,
+                              'form': form,
+                              }, context_instance=RequestContext(request))
+
+def answer(request, id):
+    question = get_object_or_404(Question, id=id)
+
+    if request.POST:
+        form = AnswerForm(request.POST, request.user)
+
+        if request.session.pop('reviewing_pending_data', False) or not form.is_valid():
+            request.session['redirect_POST_data'] = request.POST
+            return HttpResponseRedirect(question.get_absolute_url() + '#fmanswer')
+
+        if request.user.is_authenticated() and request.user.email_valid_and_can_answer():
+            answer_action = AnswerAction(user=request.user, ip=request.META['REMOTE_ADDR']).save(dict(question=question, **form.cleaned_data))
+            answer = answer_action.node
+
+            if settings.WIKI_ON and request.POST.get('wiki', False):
+                answer.nstate.wiki = answer_action
+
+            return HttpResponseRedirect(answer.get_absolute_url())
+        else:
+            request.session['pending_submission_data'] = {
+                'POST': request.POST,
+                'data_name': _("answer"),
+                'type': 'answer',
+                'submission_url': reverse('answer', kwargs={'id': id}),
+                'time': datetime.datetime.now()
+            }
+
+            if request.user.is_authenticated():
+                request.user.message_set.create(message=_("Your answer is pending until you %s.") % html.hyperlink(
+                    reverse('send_validation_email'), _("validate your email")
+                ))
+                return HttpResponseRedirect(question.get_absolute_url())
+            else:
+                return HttpResponseRedirect(reverse('auth_signin'))
+
+    return HttpResponseRedirect(question.get_absolute_url())
+
+
+def manage_pending_data(request, action, forward=None):
+    pending_data = request.session.pop('pending_submission_data', None)
+
+    if not pending_data:
+        raise Http404
+
+    if action == _("cancel"):
+        return HttpResponseRedirect(forward or request.META.get('HTTP_REFERER', '/'))
+    else:
+        if action == _("review"):
+            request.session['reviewing_pending_data'] = True
+
+        request.session['redirect_POST_data'] = pending_data['POST']
+        return HttpResponseRedirect(pending_data['submission_url'])
+
+
diff --git a/forum/modules/template_loader.py/forum_modules/__init__.py b/forum/modules/template_loader.py/forum_modules/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/forum/modules/template_loader.py/forum_modules/akismet/__init__.py b/forum/modules/template_loader.py/forum_modules/akismet/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/forum/modules/template_loader.py/forum_modules/akismet/lib/__init__.py b/forum/modules/template_loader.py/forum_modules/akismet/lib/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/forum/modules/template_loader.py/forum_modules/akismet/lib/akismet.py b/forum/modules/template_loader.py/forum_modules/akismet/lib/akismet.py
new file mode 100644 (file)
index 0000000..fd15794
--- /dev/null
@@ -0,0 +1,373 @@
+# Version 0.2.0
+# 2009/06/18
+
+# Copyright Michael Foord 2005-2009
+# akismet.py
+# Python interface to the akismet API
+# E-mail fuzzyman@voidspace.org.uk
+
+# http://www.voidspace.org.uk/python/modules.shtml
+# http://akismet.com
+
+# Released subject to the BSD License
+# See http://www.voidspace.org.uk/python/license.shtml
+
+
+"""
+A python interface to the `Akismet <http://akismet.com>`_ API.
+This is a web service for blocking SPAM comments to blogs - or other online 
+services.
+
+You will need a Wordpress API key, from `wordpress.com <http://wordpress.com>`_.
+
+You should pass in the keyword argument 'agent' to the name of your program,
+when you create an Akismet instance. This sets the ``user-agent`` to a useful
+value.
+
+The default is : ::
+
+    Python Interface by Fuzzyman | akismet.py/0.2.0
+
+Whatever you pass in, will replace the *Python Interface by Fuzzyman* part.
+**0.2.0** will change with the version of this interface.
+
+Usage example::
+    
+    from akismet import Akismet
+    
+    api = Akismet(agent='Test Script')
+    # if apikey.txt is in place,
+    # the key will automatically be set
+    # or you can call api.setAPIKey()
+    #
+    if api.key is None:
+        print "No 'apikey.txt' file."
+    elif not api.verify_key():
+        print "The API key is invalid."
+    else:
+        # data should be a dictionary of values
+        # They can all be filled in with defaults
+        # from a CGI environment
+        if api.comment_check(comment, data):
+            print 'This comment is spam.'
+        else:
+            print 'This comment is ham.'
+"""
+
+
+import os, sys
+from urllib import urlencode
+from forum import settings
+
+import socket
+if hasattr(socket, 'setdefaulttimeout'):
+    # Set the default timeout on sockets to 5 seconds
+    socket.setdefaulttimeout(5)
+
+__version__ = '0.2.0'
+
+__all__ = (
+    '__version__',
+    'Akismet',
+    'AkismetError',
+    'APIKeyError',
+    )
+
+__author__ = 'Michael Foord <fuzzyman AT voidspace DOT org DOT uk>'
+
+__docformat__ = "restructuredtext en"
+
+user_agent = "%s | akismet.py/%s"
+DEFAULTAGENT = 'Python Interface by Fuzzyman/%s'
+
+isfile = os.path.isfile
+
+urllib2 = None
+try:
+    from google.appengine.api import urlfetch
+except ImportError:
+    import urllib2
+
+if urllib2 is None:
+    def _fetch_url(url, data, headers):
+        req = urlfetch.fetch(url=url, payload=data, method=urlfetch.POST, headers=headers)
+        if req.status_code == 200:
+            return req.content
+        raise Exception('Could not fetch Akismet URL: %s Response code: %s' % 
+                        (url, req.status_code))
+else:
+    def _fetch_url(url, data, headers):
+        req = urllib2.Request(url, data, headers)
+        h = urllib2.urlopen(req)
+        resp = h.read()
+        return resp
+
+
+class AkismetError(Exception):
+    """Base class for all akismet exceptions."""
+
+class APIKeyError(AkismetError):
+    """Invalid API key."""
+
+class Akismet(object):
+    """A class for working with the akismet API"""
+
+    baseurl = 'rest.akismet.com/1.1/'
+
+    def __init__(self, key=None, blog_url=None, agent=None):
+        """Automatically calls ``setAPIKey``."""
+        if agent is None:
+            agent = DEFAULTAGENT % __version__
+        self.user_agent = user_agent % (agent, __version__)
+        self.setAPIKey(key, blog_url)
+
+
+    def _getURL(self):
+        """
+        Fetch the url to make requests to.
+        
+        This comprises of api key plus the baseurl.
+        """
+        return 'http://%s.%s' % (self.key, self.baseurl)
+    
+    
+    def _safeRequest(self, url, data, headers):
+        try:
+            resp = _fetch_url(url, data, headers)
+        except Exception, e:
+            raise AkismetError(str(e))
+        return resp
+
+
+    def setAPIKey(self, key=None, blog_url=None):
+        """
+        Set the wordpress API key for all transactions.
+
+        If you don't specify an explicit API ``key`` and ``blog_url`` it will
+        attempt to load them from a file called ``apikey.txt`` in the current
+        directory.
+
+        This method is *usually* called automatically when you create a new
+        ``Akismet`` instance.
+        """
+        if key is None and isfile('apikey.txt'):
+            the_file = [l.strip() for l in open('apikey.txt').readlines()
+                if l.strip() and not l.strip().startswith('#')]
+            try:
+                self.key = the_file[0]
+                self.blog_url = the_file[1]
+            except IndexError:
+                raise APIKeyError("Your 'apikey.txt' is invalid.")
+        else:
+            self.key = key
+            self.blog_url = blog_url
+
+
+    def verify_key(self):
+        """
+        This equates to the ``verify-key`` call against the akismet API.
+        
+        It returns ``True`` if the key is valid.
+        
+        The docs state that you *ought* to call this at the start of the
+        transaction.
+        
+        It raises ``APIKeyError`` if you have not yet set an API key.
+        
+        If the connection to akismet fails, it allows the normal ``HTTPError``
+        or ``URLError`` to be raised.
+        (*akismet.py* uses `urllib2 <http://docs.python.org/lib/module-urllib2.html>`_)
+        """
+        if self.key is None:
+            raise APIKeyError("Your have not set an API key.")
+        data = { 'key': self.key, 'blog': self.blog_url }
+        # this function *doesn't* use the key as part of the URL
+        url = 'http://%sverify-key' % self.baseurl
+        # we *don't* trap the error here
+        # so if akismet is down it will raise an HTTPError or URLError
+        headers = {'User-Agent' : self.user_agent}
+        resp = self._safeRequest(url, urlencode(data), headers)
+        if resp.lower() == 'valid':
+            return True
+        else:
+            return False
+
+    def _build_data(self, comment, data):
+        """
+        This function builds the data structure required by ``comment_check``,
+        ``submit_spam``, and ``submit_ham``.
+        
+        It modifies the ``data`` dictionary you give it in place. (and so
+        doesn't return anything)
+        
+        It raises an ``AkismetError`` if the user IP or user-agent can't be
+        worked out.
+        """
+        data['comment_content'] = comment
+        if not 'user_ip' in data:
+            try:
+                val = os.environ['REMOTE_ADDR']
+            except KeyError:
+                raise AkismetError("No 'user_ip' supplied")
+            data['user_ip'] = val
+        if not 'user_agent' in data:
+            try:
+                val = os.environ['HTTP_USER_AGENT']
+            except KeyError:
+                raise AkismetError("No 'user_agent' supplied")
+            data['user_agent'] = val
+        #
+        data.setdefault('referrer', os.environ.get('HTTP_REFERER', 'unknown'))
+        data.setdefault('permalink', '')
+        data.setdefault('comment_type', 'comment')
+        data.setdefault('comment_author', '')
+        data.setdefault('comment_author_email', '')
+        data.setdefault('comment_author_url', '')
+        data.setdefault('SERVER_ADDR', os.environ.get('SERVER_ADDR', ''))
+        data.setdefault('SERVER_ADMIN', os.environ.get('SERVER_ADMIN', ''))
+        data.setdefault('SERVER_NAME', os.environ.get('SERVER_NAME', ''))
+        data.setdefault('SERVER_PORT', os.environ.get('SERVER_PORT', ''))
+        data.setdefault('SERVER_SIGNATURE', os.environ.get('SERVER_SIGNATURE',
+            ''))
+        data.setdefault('SERVER_SOFTWARE', os.environ.get('SERVER_SOFTWARE',
+            ''))
+        data.setdefault('HTTP_ACCEPT', os.environ.get('HTTP_ACCEPT', ''))
+        data.setdefault('blog', self.blog_url)
+
+
+    def comment_check(self, comment, data=None, build_data=True, DEBUG=False):
+        """
+        This is the function that checks comments.
+        
+        It returns ``True`` for spam and ``False`` for ham.
+        
+        If you set ``DEBUG=True`` then it will return the text of the response,
+        instead of the ``True`` or ``False`` object.
+        
+        It raises ``APIKeyError`` if you have not yet set an API key.
+        
+        If the connection to Akismet fails then the ``HTTPError`` or
+        ``URLError`` will be propogated.
+        
+        As a minimum it requires the body of the comment. This is the
+        ``comment`` argument.
+        
+        Akismet requires some other arguments, and allows some optional ones.
+        The more information you give it, the more likely it is to be able to
+        make an accurate diagnosise.
+        
+        You supply these values using a mapping object (dictionary) as the
+        ``data`` argument.
+        
+        If ``build_data`` is ``True`` (the default), then *akismet.py* will
+        attempt to fill in as much information as possible, using default
+        values where necessary. This is particularly useful for programs
+        running in a {acro;CGI} environment. A lot of useful information
+        can be supplied from evironment variables (``os.environ``). See below.
+        
+        You *only* need supply values for which you don't want defaults filled
+        in for. All values must be strings.
+        
+        There are a few required values. If they are not supplied, and
+        defaults can't be worked out, then an ``AkismetError`` is raised.
+        
+        If you set ``build_data=False`` and a required value is missing an
+        ``AkismetError`` will also be raised.
+        
+        The normal values (and defaults) are as follows : ::
+        
+            'user_ip':          os.environ['REMOTE_ADDR']       (*)
+            'user_agent':       os.environ['HTTP_USER_AGENT']   (*)
+            'referrer':         os.environ.get('HTTP_REFERER', 'unknown') [#]_
+            'permalink':        ''
+            'comment_type':     'comment' [#]_
+            'comment_author':   ''
+            'comment_author_email': ''
+            'comment_author_url': ''
+            'SERVER_ADDR':      os.environ.get('SERVER_ADDR', '')
+            'SERVER_ADMIN':     os.environ.get('SERVER_ADMIN', '')
+            'SERVER_NAME':      os.environ.get('SERVER_NAME', '')
+            'SERVER_PORT':      os.environ.get('SERVER_PORT', '')
+            'SERVER_SIGNATURE': os.environ.get('SERVER_SIGNATURE', '')
+            'SERVER_SOFTWARE':  os.environ.get('SERVER_SOFTWARE', '')
+            'HTTP_ACCEPT':      os.environ.get('HTTP_ACCEPT', '')
+        
+        (*) Required values
+        
+        You may supply as many additional 'HTTP_*' type values as you wish.
+        These should correspond to the http headers sent with the request.
+        
+        .. [#] Note the spelling "referrer". This is a required value by the
+            akismet api - however, referrer information is not always
+            supplied by the browser or server. In fact the HTTP protocol
+            forbids relying on referrer information for functionality in 
+            programs.
+        .. [#] The `API docs <http://akismet.com/development/api/>`_ state that this value
+            can be " *blank, comment, trackback, pingback, or a made up value*
+            *like 'registration'* ".
+        """
+        if self.key is None:
+            raise APIKeyError("Your have not set an API key.")
+        if data is None:
+            data = {}
+        if build_data:
+            self._build_data(comment, data)
+        if 'blog' not in data:
+            data['blog'] = self.blog_url
+        url = '%scomment-check' % self._getURL()
+        # we *don't* trap the error here
+        # so if akismet is down it will raise an HTTPError or URLError
+        headers = {'User-Agent' : self.user_agent}
+        resp = self._safeRequest(url, urlencode(data), headers)
+        if DEBUG:
+            return resp
+        resp = resp.lower()
+        if resp == 'true':
+            return True
+        elif resp == 'false':
+            return False
+        else:
+            # NOTE: Happens when you get a 'howdy wilbur' response !
+            raise AkismetError('missing required argument.')
+
+
+    def submit_spam(self, comment, data=None, build_data=True):
+        """
+        This function is used to tell akismet that a comment it marked as ham,
+        is really spam.
+        
+        It takes all the same arguments as ``comment_check``, except for
+        *DEBUG*.
+        """
+        if self.key is None:
+            raise APIKeyError("Your have not set an API key.")
+        if data is None:
+            data = {}
+        if build_data:
+            self._build_data(comment, data)
+        url = '%ssubmit-spam' % self._getURL()
+        # we *don't* trap the error here
+        # so if akismet is down it will raise an HTTPError or URLError
+        headers = {'User-Agent' : self.user_agent}
+        self._safeRequest(url, urlencode(data), headers)
+
+
+    def submit_ham(self, comment, data=None, build_data=True):
+        """
+        This function is used to tell akismet that a comment it marked as spam,
+        is really ham.
+        
+        It takes all the same arguments as ``comment_check``, except for
+        *DEBUG*.
+        """
+        if self.key is None:
+            raise APIKeyError("Your have not set an API key.")
+        if data is None:
+            data = {}
+        if build_data:
+            self._build_data(comment, data)
+        url = '%ssubmit-ham' % self._getURL()
+        # we *don't* trap the error here
+        # so if akismet is down it will raise an HTTPError or URLError
+        headers = {'User-Agent' : self.user_agent}
+        self._safeRequest(url, urlencode(data), headers)
diff --git a/forum/modules/template_loader.py/forum_modules/akismet/settings.py b/forum/modules/template_loader.py/forum_modules/akismet/settings.py
new file mode 100644 (file)
index 0000000..209f8e5
--- /dev/null
@@ -0,0 +1,13 @@
+from forum.settings.base import Setting\r
+from forum.settings.extkeys import EXT_KEYS_SET\r
+from forum.settings.minrep import MIN_REP_SET\r
+from django.utils.translation import ugettext_lazy as _\r
+\r
+WORDPRESS_API_KEY = Setting('WORDPRESS_API_KEY', '', EXT_KEYS_SET, dict(\r
+label = _("WordPress API key"),\r
+help_text = _("Your WordPress API key. You can get one at <a href='http://wordpress.com/'>http://wordpress.com/</a>"),\r
+required=False))\r
+\r
+REP_FOR_NO_SPAM_CHECK = Setting('REP_FOR_NO_SPAM_CHECK', 750, MIN_REP_SET, dict(\r
+label = _("Minimum reputation to not have your posts checked"),\r
+help_text = _("The minimum reputation a user must have so that when they post a question, answer or comment it is not checked for spam.")))\r
diff --git a/forum/modules/template_loader.py/forum_modules/akismet/startup.py b/forum/modules/template_loader.py/forum_modules/akismet/startup.py
new file mode 100644 (file)
index 0000000..2107bbb
--- /dev/null
@@ -0,0 +1,77 @@
+from django.utils.translation import ugettext as _
+from django.http import HttpResponse, HttpResponseRedirect
+from django.template import RequestContext
+from django.utils import simplejson
+from django.utils.encoding import smart_str
+from django.shortcuts import render_to_response
+from forum.modules import decorate
+from forum import views
+from lib.akismet import Akismet
+from forum.settings import APP_URL, OSQA_VERSION
+
+from settings import WORDPRESS_API_KEY, REP_FOR_NO_SPAM_CHECK
+
+from forum.models.user import User
+from forum.forms.general import SimpleCaptchaForm
+
+import settings
+import logging
+
+def can_bypass_spam_check(user):
+    return user.is_authenticated and (user.is_superuser or user.is_staff or cmp(int(user.reputation), REP_FOR_NO_SPAM_CHECK) > 0)
+
+
+def check_spam(param, comment_type):
+    def wrapper(origin, request, *args, **kwargs):
+        if request.POST and request.POST.get(param, None) and WORDPRESS_API_KEY and (not can_bypass_spam_check(request.user)):
+        
+            comment = smart_str(request.POST[param])
+
+            data = {
+            "user_ip":request.META["REMOTE_ADDR"],
+            "user_agent":request.environ['HTTP_USER_AGENT'],
+            "comment_type": comment_type,
+            "comment":comment
+            }
+
+            if request.user.is_authenticated():
+                data.update({
+                "comment_author":smart_str(request.user.username),
+                "comment_author_email":request.user.email,
+                "comment_author_url":request.user.website,
+                })
+
+            api = Akismet(settings.WORDPRESS_API_KEY, APP_URL, "OSQA/%s" % OSQA_VERSION)
+            if api.comment_check(comment, data):
+                post_data = request.POST
+                captcha_form = SimpleCaptchaForm(request.POST)
+                
+                if request.is_ajax():
+                    response = {
+                    'success': False,
+                    'error_message': _("Sorry, but akismet thinks your %s is spam.") % comment_type
+                    }
+                    return HttpResponse(simplejson.dumps(response), mimetype="application/json")
+                else:
+                    captcha_checked = False
+                    try:
+                        if captcha_form.is_valid() and 'recaptcha' in captcha_form.fields.keys():
+                            captcha_checked = True
+                    except:
+                        pass
+
+                    if not captcha_checked:
+                        return render_to_response('modules/akismet/foundspam.html', {
+                        'action_name': comment_type,
+                        'post_data' : post_data,
+                        'captcha_form' : captcha_form,
+                        }, RequestContext(request))
+
+        return origin(request, *args, **kwargs)
+
+    return wrapper
+
+
+decorate(views.writers.ask)(check_spam('text', _('question')))
+decorate(views.writers.answer)(check_spam('text', _('answer')))
+decorate(views.commands.comment)(check_spam('comment', _('comment')))
diff --git a/forum/modules/template_loader.py/forum_modules/akismet/templates/foundspam.html b/forum/modules/template_loader.py/forum_modules/akismet/templates/foundspam.html
new file mode 100644 (file)
index 0000000..77251c7
--- /dev/null
@@ -0,0 +1,36 @@
+{% extends "base_content.html" %}
+{% load i18n %}
+{% block title %}{% trans "Akismet message" %}{% endblock %}
+
+{% block content %}
+<div class="headNormal">
+{% blocktrans %}Akismet believes your {{ action_name }} is spam.{% endblocktrans %}
+</div>
+<div class="content">
+{% blocktrans %}
+We're sorry, but Akismet believes your {{ action_name }} is spam.<br />
+If you believe this is an error, please contact the forum administrator.
+{% endblocktrans %}
+
+{% if captcha_form.recaptcha %}
+<form action="." method="post">
+<table>
+       <tr>
+               <td>
+               {% for post_item in post_data.items %}
+               <input type="hidden" name="{{ post_item.0 }}" value="{{ post_item.1 }}" />
+               {% endfor %}
+
+               {{ captcha_form.recaptcha }}
+               
+               </td>
+       </tr>
+       <tr>
+               <td><input type="submit" value"{% trans "Submit" %} /></td>
+       </tr>
+</table>
+</form>
+{% endif %}
+
+</div>
+{% endblock %}
diff --git a/forum/modules/template_loader.py/forum_modules/default_badges/__init__.py b/forum/modules/template_loader.py/forum_modules/default_badges/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/forum/modules/template_loader.py/forum_modules/default_badges/badges.py b/forum/modules/template_loader.py/forum_modules/default_badges/badges.py
new file mode 100644 (file)
index 0000000..f0a8930
--- /dev/null
@@ -0,0 +1,322 @@
+from datetime import datetime, timedelta
+from django.utils.translation import ugettext as _
+from forum.badges.base import AbstractBadge
+from forum.models import Badge
+from forum.actions import *
+from forum.models import Vote, Flag
+
+import settings
+
+class QuestionViewBadge(AbstractBadge):
+    abstract = True
+    listen_to = (QuestionViewAction,)
+
+    @property
+    def description(self):
+        return _('Asked a question with %s views') % str(self.nviews)
+
+    def award_to(self, action):
+        if action.node.extra_count == int(self.nviews):
+            return action.node.author
+
+
+class PopularQuestion(QuestionViewBadge):
+    name = _('Popular Question')
+    nviews = settings.POPULAR_QUESTION_VIEWS
+
+
+class NotableQuestion(QuestionViewBadge):
+    type = Badge.SILVER
+    name = _('Notable Question')
+    nviews = settings.NOTABLE_QUESTION_VIEWS
+
+class FamousQuestion(QuestionViewBadge):
+    type = Badge.GOLD
+    name = _('Famous Question')
+    nviews = settings.FAMOUS_QUESTION_VIEWS
+
+
+class NodeScoreBadge(AbstractBadge):
+    abstract = True
+    listen_to = (VoteAction,)
+
+    def award_to(self, action):
+        if (action.node.node_type == self.node_type) and (action.node.score == int(self.expected_score)):
+            return action.node.author
+
+
+class QuestionScoreBadge(NodeScoreBadge):
+    abstract = True
+    node_type = "question"
+
+    @property
+    def description(self):
+        return _('Question voted up %s times') % str(self.expected_score)
+
+class NiceQuestion(QuestionScoreBadge):
+    expected_score = settings.NICE_QUESTION_VOTES_UP
+    name = _("Nice Question")
+
+class GoodQuestion(QuestionScoreBadge):
+    type = Badge.SILVER
+    expected_score = settings.GOOD_QUESTION_VOTES_UP
+    name = _("Good Question")
+
+class GreatQuestion(QuestionScoreBadge):
+    type = Badge.GOLD
+    expected_score = settings.GREAT_QUESTION_VOTES_UP
+    name = _("Great Question")
+
+
+class AnswerScoreBadge(NodeScoreBadge):
+    abstract = True
+    node_type = "answer"
+
+    @property
+    def description(self):
+        return _('Answer voted up %s times') % str(self.expected_score)
+
+class NiceAnswer(AnswerScoreBadge):
+    expected_score = settings.NICE_ANSWER_VOTES_UP
+    name = _("Nice Answer")
+
+class GoodAnswer(AnswerScoreBadge):
+    type = Badge.SILVER
+    expected_score = settings.GOOD_ANSWER_VOTES_UP
+    name = _("Good Answer")
+
+class GreatAnswer(AnswerScoreBadge):
+    type = Badge.GOLD
+    expected_score = settings.GREAT_ANSWER_VOTES_UP
+    name = _("Great Answer")
+
+
+class FavoriteQuestionBadge(AbstractBadge):
+    abstract = True
+    listen_to = (FavoriteAction,)
+
+    @property
+    def description(self):
+        return _('Question favorited by %s users') % str(self.expected_count)
+
+    def award_to(self, action):
+        if (action.node.node_type == "question") and (action.node.favorite_count == int(self.expected_count)):
+            return action.node.author
+
+class FavoriteQuestion(FavoriteQuestionBadge):
+    type = Badge.SILVER
+    name = _("Favorite Question")
+    expected_count = settings.FAVORITE_QUESTION_FAVS
+
+class StellarQuestion(FavoriteQuestionBadge):
+    type = Badge.GOLD
+    name = _("Stellar Question")
+    expected_count = settings.STELLAR_QUESTION_FAVS
+
+
+class Disciplined(AbstractBadge):
+    listen_to = (DeleteAction,)
+    name = _("Disciplined")
+    description = _('Deleted own post with score of %s or higher') % settings.DISCIPLINED_MIN_SCORE
+
+    def award_to(self, action):
+        if (action.node.author == action.user) and (action.node.score >= int(settings.DISCIPLINED_MIN_SCORE)):
+            return action.user
+
+class PeerPressure(AbstractBadge):
+    listen_to = (DeleteAction,)
+    name = _("Peer Pressure")
+    description = _('Deleted own post with score of %s or lower') % settings.PEER_PRESSURE_MAX_SCORE
+
+    def award_to(self, action):
+        if (action.node.author == action.user) and (action.node.score <= int(settings.PEER_PRESSURE_MAX_SCORE)):
+            return action.user
+
+
+class Critic(AbstractBadge):
+    award_once = True
+    listen_to = (VoteDownAction,)
+    name = _("Critic")
+    description = _('First down vote')
+
+    def award_to(self, action):
+        if (action.user.vote_down_count == 1):
+            return action.user
+
+
+class Supporter(AbstractBadge):
+    award_once = True
+    listen_to = (VoteUpAction,)
+    name = _("Supporter")
+    description = _('First up vote')
+
+    def award_to(self, action):
+        if (action.user.vote_up_count == 1):
+            return action.user
+
+
+class FirstActionBadge(AbstractBadge):
+    award_once = True
+    abstract = True
+
+    def award_to(self, action):
+        if (self.listen_to[0].objects.filter(user=action.user).count() == 1):
+            return action.user
+
+class CitizenPatrol(FirstActionBadge):
+    listen_to = (FlagAction,)
+    name = _("Citizen Patrol")
+    description = _('First flagged post')
+
+class Organizer(FirstActionBadge):
+    listen_to = (RetagAction,)
+    name = _("Organizer")
+    description = _('First retag')
+
+class Editor(FirstActionBadge):
+    listen_to = (ReviseAction,)
+    name = _("Editor")
+    description = _('First edit')
+
+class Scholar(FirstActionBadge):
+    listen_to = (AcceptAnswerAction,)
+    name = _("Scholar")
+    description = _('First accepted answer on your own question')
+
+class Cleanup(FirstActionBadge):
+    listen_to = (RollbackAction,)
+    name = _("Cleanup")
+    description = _('First rollback')
+
+
+class Autobiographer(AbstractBadge):
+    award_once = True
+    listen_to = (EditProfileAction,)
+    name = _("Autobiographer")
+    description = _('Completed all user profile fields')
+
+    def award_to(self, action):
+        user = action.user
+        if user.email and user.real_name and user.website and user.location and \
+                user.date_of_birth and user.about:
+            return user
+
+
+class CivicDuty(AbstractBadge):
+    type = Badge.SILVER
+    award_once = True
+    listen_to = (VoteUpAction, VoteDownAction)
+    name = _("Civic Duty")
+    description = _('Voted %s times') % settings.CIVIC_DUTY_VOTES
+
+    def award_to(self, action):
+        if (action.user.vote_up_count + action.user.vote_down_count) == int(settings.CIVIC_DUTY_VOTES):
+            return action.user
+
+
+class Pundit(AbstractBadge):
+    award_once = True
+    listen_to = (CommentAction,)
+    name = _("Pundit")
+    description = _('Left %s comments') % settings.PUNDIT_COMMENT_COUNT
+
+    def award_to(self, action):
+        if action.user.nodes.filter_state(deleted=False).filter(node_type="comment").count() == int(
+                settings.PUNDIT_COMMENT_COUNT):
+            return action.user
+
+
+class SelfLearner(AbstractBadge):
+    listen_to = (VoteUpAction, )
+    name = _("Self Learner")
+    description = _('Answered your own question with at least %s up votes') % settings.SELF_LEARNER_UP_VOTES
+
+    def award_to(self, action):
+        if (action.node.node_type == "answer") and (action.node.author == action.node.parent.author) and (
+        action.node.score == int(settings.SELF_LEARNER_UP_VOTES)):
+            return action.node.author
+
+
+class StrunkAndWhite(AbstractBadge):
+    type = Badge.SILVER
+    award_once = True
+    listen_to = (ReviseAction,)
+    name = _("Strunk & White")
+    description = _('Edited %s entries') % settings.STRUNK_AND_WHITE_EDITS
+
+    def award_to(self, action):
+        if (ReviseAction.objects.filter(user=action.user).count() == int(settings.STRUNK_AND_WHITE_EDITS)):
+            return action.user
+
+
+class Student(AbstractBadge):
+    award_once = True
+    listen_to = (VoteUpAction,)
+    name = _("Student")
+    description = _('Asked first question with at least one up vote')
+
+    def award_to(self, action):
+        if (action.node.node_type == "question") and (action.node.author.nodes.filter_state(deleted=False).filter(
+                node_type="question", score=1).count() == 1):
+            return action.node.author
+
+
+class Teacher(AbstractBadge):
+    award_once = True
+    listen_to = (VoteUpAction,)
+    name = _("Teacher")
+    description = _('Answered first question with at least one up vote')
+
+    def award_to(self, action):
+        if (action.node.node_type == "answer") and (action.node.author.nodes.filter_state(deleted=False).filter(
+                node_type="answer", score=1).count() == 1):
+            return action.node.author
+
+
+class Enlightened(AbstractBadge):
+    type = Badge.SILVER
+    award_once = True
+    listen_to = (VoteUpAction, AcceptAnswerAction)
+    name = _("Enlightened")
+    description = _('First answer was accepted with at least %s up votes') % settings.ENLIGHTENED_UP_VOTES
+
+    def award_to(self, action):
+        if (action.node.node_type == "answer") and (action.node.accepted) and (
+        action.node.score >= int(settings.ENLIGHTENED_UP_VOTES)):
+            return action.node.author
+
+
+class Guru(AbstractBadge):
+    type = Badge.SILVER
+    listen_to = (VoteUpAction, AcceptAnswerAction)
+    name = _("Guru")
+    description = _('Accepted answer and voted up %s times') % settings.GURU_UP_VOTES
+
+    def award_to(self, action):
+        if (action.node.node_type == "answer") and (action.node.accepted) and (
+        action.node.score >= int(settings.GURU_UP_VOTES)):
+            return action.node.author
+
+
+class Necromancer(AbstractBadge):
+    type = Badge.SILVER
+    listen_to = (VoteUpAction,)
+    name = _("Necromancer")
+    description = _('Answered a question more than %(dif_days)s days later with at least %(up_votes)s votes') % \
+            {'dif_days': settings.NECROMANCER_DIF_DAYS, 'up_votes': settings.NECROMANCER_UP_VOTES}
+
+    def award_to(self, action):
+        if (action.node.node_type == "answer") and (
+        action.node.added_at >= (action.node.question.added_at + timedelta(days=int(settings.NECROMANCER_DIF_DAYS)))
+        ) and (action.node.score == settings.NECROMANCER_UP_VOTES):
+            return action.node.author
+
+class Taxonomist(AbstractBadge):
+    type = Badge.SILVER
+    listen_to = tuple()
+    name = _("Taxonomist")
+    description = _('Created a tag used by %s questions') % settings.TAXONOMIST_USE_COUNT
+
+    def award_to(self, action):
+        return None
+
diff --git a/forum/modules/template_loader.py/forum_modules/default_badges/settings.py b/forum/modules/template_loader.py/forum_modules/default_badges/settings.py
new file mode 100644 (file)
index 0000000..a0f118e
--- /dev/null
@@ -0,0 +1,136 @@
+from forum.settings import BADGES_SET
+from forum.settings.base import Setting
+from django.utils.translation import ugettext_lazy as _
+
+POPULAR_QUESTION_VIEWS = Setting('POPULAR_QUESTION_VIEWS', 1000, BADGES_SET, dict(
+label = _("Popular Question views"),
+help_text = _("""
+Number of question views required to award a Popular Question badge to the question author
+""")))
+
+NOTABLE_QUESTION_VIEWS = Setting('NOTABLE_QUESTION_VIEWS', 2500, BADGES_SET, dict(
+label = _("Notable Question views"),
+help_text = _("""
+Number of question views required to award a Notable Question badge to the question author
+""")))
+
+FAMOUS_QUESTION_VIEWS = Setting('FAMOUS_QUESTION_VIEWS', 10000, BADGES_SET, dict(
+label = _("Famous Question views"),
+help_text = _("""
+Number of question views required to award a Famous Question badge to the question author
+""")))
+
+NICE_ANSWER_VOTES_UP = Setting('NICE_ANSWER_VOTES_UP', 10, BADGES_SET, dict(
+label = _("Nice Answer up votes"),
+help_text = _("""
+Number of up votes required to award a Nice Answer badge to the answer author
+""")))
+
+NICE_QUESTION_VOTES_UP = Setting('NICE_QUESTION_VOTES_UP', 10, BADGES_SET, dict(
+label = _("Nice Question up votes"),
+help_text = _("""
+Number of up votes required to award a Nice Question badge to the question author
+""")))
+
+GOOD_ANSWER_VOTES_UP = Setting('GOOD_ANSWER_VOTES_UP', 25, BADGES_SET, dict(
+label = _("Good Answer up votes"),
+help_text = _("""
+Number of up votes required to award a Good Answer badge to the answer author
+""")))
+
+GOOD_QUESTION_VOTES_UP = Setting('GOOD_QUESTION_VOTES_UP', 25, BADGES_SET, dict(
+label = _("Good Question up votes"),
+help_text = _("""
+Number of up votes required to award a Good Question badge to the question author
+""")))
+
+GREAT_ANSWER_VOTES_UP = Setting('GREAT_ANSWER_VOTES_UP', 100, BADGES_SET, dict(
+label = _("Great Answer up votes"),
+help_text = _("""
+Number of up votes required to award a Great Answer badge to the answer author
+""")))
+
+GREAT_QUESTION_VOTES_UP = Setting('GREAT_QUESTION_VOTES_UP', 100, BADGES_SET, dict(
+label = _("Great Question up votes"),
+help_text = _("""
+Number of up votes required to award a Great Question badge to the question author
+""")))
+
+FAVORITE_QUESTION_FAVS = Setting('FAVORITE_QUESTION_FAVS', 25, BADGES_SET, dict(
+label = _("Favorite Question favorite count"),
+help_text = _("""
+How many times a question needs to be favorited by other users to award a Favorite Question badge to the question author
+""")))
+
+STELLAR_QUESTION_FAVS = Setting('STELLAR_QUESTION_FAVS', 100, BADGES_SET, dict(
+label = _("Stellar Question favorite count"),
+help_text = _("""
+How many times a question needs to be favorited by other users to award a Stellar Question badge to the question author
+""")))
+
+DISCIPLINED_MIN_SCORE = Setting('DISCIPLINED_MIN_SCORE', 3, BADGES_SET, dict(
+label = _("Disciplined minimum score"),
+help_text = _("""
+Minimum score a question needs to have to award the Disciplined badge to an author of a question who deletes it.
+""")))
+
+PEER_PRESSURE_MAX_SCORE = Setting('PEER_PRESSURE_MAX_SCORE', -3, BADGES_SET, dict(
+label = _("Peer Pressure maximum score"),
+help_text = _("""
+Maximum score a question needs to have to award the Peer Pressure badge to an author of a question who deletes it.
+""")))
+
+CIVIC_DUTY_VOTES = Setting('CIVIC_DUTY_VOTES', 300, BADGES_SET, dict(
+label = _("Civic Duty votes"),
+help_text = _("""
+Number of votes an user needs to cast to be awarded the Civic Duty badge.
+""")))
+
+PUNDIT_COMMENT_COUNT = Setting('PUNDIT_COMMENT_COUNT', 10, BADGES_SET, dict(
+label = _("Pundit number of comments"),
+help_text = _("""
+Number of comments an user needs to post to be awarded the Pundit badge.
+""")))
+
+SELF_LEARNER_UP_VOTES = Setting('SELF_LEARNER_UP_VOTES', 3, BADGES_SET, dict(
+label = _("Self Learner up votes"),
+help_text = _("""
+Number of up votes an answer from the question author needs to have for the author to be awarded the Self Learner badge.
+""")))
+
+STRUNK_AND_WHITE_EDITS = Setting('STRUNK_AND_WHITE_EDITS', 100, BADGES_SET, dict(
+label = _("Strunk and White updates"),
+help_text = _("""
+Number of question or answer updates an user needs to make to be awarded the Strunk & White badge.
+""")))
+
+ENLIGHTENED_UP_VOTES = Setting('ENLIGHTENED_UP_VOTES', 10, BADGES_SET, dict(
+label = _("Enlightened up votes"),
+help_text = _("""
+Number of up votes an accepted answer needs to have for the author to be awarded the Enlightened badge.
+""")))
+
+GURU_UP_VOTES = Setting('GURU_UP_VOTES', 40, BADGES_SET, dict(
+label = _("Guru up votes"),
+help_text = _("""
+Number of up votes an accepted answer needs to have for the author to be awarded the Guru badge.
+""")))
+
+NECROMANCER_UP_VOTES = Setting('NECROMANCER_UP_VOTES', 5, BADGES_SET, dict(
+label = _("Necromancer up votes"),
+help_text = _("""
+Number of up votes an answer needs to have for the author to be awarded the Necromancer badge.
+""")))
+
+NECROMANCER_DIF_DAYS = Setting('NECROMANCER_DIF_DAYS', 60, BADGES_SET, dict(
+label = _("Necromancer difference in days"),
+help_text = _("""
+Difference in days betwen the posted date of a question and an answer for the answer author to be awarded the Necromancer badge.
+""")))
+
+TAXONOMIST_USE_COUNT = Setting('TAXONOMIST_USE_COUNT', 50, BADGES_SET, dict(
+label = _("Taxonomist usage count"),
+help_text = _("""
+How many usages a tag needs to have for the tag creator to be awarded the Taxonomist badge. 
+""")))
+
diff --git a/forum/modules/template_loader.py/forum_modules/exporter/__init__.py b/forum/modules/template_loader.py/forum_modules/exporter/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/forum/modules/template_loader.py/forum_modules/exporter/backups/README b/forum/modules/template_loader.py/forum_modules/exporter/backups/README
new file mode 100644 (file)
index 0000000..14baff4
--- /dev/null
@@ -0,0 +1 @@
+you can change the location of this folder using the admin panel
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/exporter/commands.py b/forum/modules/template_loader.py/forum_modules/exporter/commands.py
new file mode 100644 (file)
index 0000000..b7950fe
--- /dev/null
@@ -0,0 +1,77 @@
+PG_SEQUENCE_RESETS = """
+SELECT setval('"auth_user_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "auth_user";
+SELECT setval('"auth_user_groups_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "auth_user_groups";
+SELECT setval('"auth_user_user_permissions_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "auth_user_user_permissions";
+SELECT setval('"forum_keyvalue_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_keyvalue";
+SELECT setval('"forum_action_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_action";
+SELECT setval('"forum_actionrepute_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_actionrepute";
+SELECT setval('"forum_subscriptionsettings_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_subscriptionsettings";
+SELECT setval('"forum_validationhash_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_validationhash";
+SELECT setval('"forum_authkeyuserassociation_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_authkeyuserassociation";
+SELECT setval('"forum_tag_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_tag";
+SELECT setval('"forum_markedtag_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_markedtag";
+SELECT setval('"forum_node_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_node";
+SELECT setval('"forum_nodestate_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_nodestate";
+SELECT setval('"forum_node_tags_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_node_tags";
+SELECT setval('"forum_noderevision_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_noderevision";
+SELECT setval('"forum_node_tags_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_node_tags";
+SELECT setval('"forum_questionsubscription_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_questionsubscription";
+SELECT setval('"forum_vote_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_vote";
+SELECT setval('"forum_flag_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_flag";
+SELECT setval('"forum_badge_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_badge";
+SELECT setval('"forum_award_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_award";
+SELECT setval('"forum_openidnonce_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_openidnonce";
+SELECT setval('"forum_openidassociation_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_openidassociation";
+"""
+
+PG_DISABLE_TRIGGERS = """
+ALTER table auth_user DISABLE TRIGGER ALL;
+ALTER table auth_user_groups DISABLE TRIGGER ALL;
+ALTER table auth_user_user_permissions DISABLE TRIGGER ALL;
+ALTER table forum_keyvalue DISABLE TRIGGER ALL;
+ALTER table forum_action DISABLE TRIGGER ALL;
+ALTER table forum_actionrepute DISABLE TRIGGER ALL;
+ALTER table forum_subscriptionsettings DISABLE TRIGGER ALL;
+ALTER table forum_validationhash DISABLE TRIGGER ALL;
+ALTER table forum_authkeyuserassociation DISABLE TRIGGER ALL;
+ALTER table forum_tag DISABLE TRIGGER ALL;
+ALTER table forum_markedtag DISABLE TRIGGER ALL;
+ALTER table forum_node DISABLE TRIGGER ALL;
+ALTER table forum_nodestate DISABLE TRIGGER ALL;
+ALTER table forum_node_tags DISABLE TRIGGER ALL;
+ALTER table forum_noderevision DISABLE TRIGGER ALL;
+ALTER table forum_node_tags DISABLE TRIGGER ALL;
+ALTER table forum_questionsubscription DISABLE TRIGGER ALL;
+ALTER table forum_vote DISABLE TRIGGER ALL;
+ALTER table forum_flag DISABLE TRIGGER ALL;
+ALTER table forum_badge DISABLE TRIGGER ALL;
+ALTER table forum_award DISABLE TRIGGER ALL;
+ALTER table forum_openidnonce DISABLE TRIGGER ALL;
+ALTER table forum_openidassociation DISABLE TRIGGER ALL;
+"""
+
+PG_ENABLE_TRIGGERS = """
+ALTER table auth_user ENABLE TRIGGER ALL;
+ALTER table auth_user_groups ENABLE TRIGGER ALL;
+ALTER table auth_user_user_permissions ENABLE TRIGGER ALL;
+ALTER table forum_keyvalue ENABLE TRIGGER ALL;
+ALTER table forum_action ENABLE TRIGGER ALL;
+ALTER table forum_actionrepute ENABLE TRIGGER ALL;
+ALTER table forum_subscriptionsettings ENABLE TRIGGER ALL;
+ALTER table forum_validationhash ENABLE TRIGGER ALL;
+ALTER table forum_authkeyuserassociation ENABLE TRIGGER ALL;
+ALTER table forum_tag ENABLE TRIGGER ALL;
+ALTER table forum_markedtag ENABLE TRIGGER ALL;
+ALTER table forum_node ENABLE TRIGGER ALL;
+ALTER table forum_nodestate ENABLE TRIGGER ALL;
+ALTER table forum_node_tags ENABLE TRIGGER ALL;
+ALTER table forum_noderevision ENABLE TRIGGER ALL;
+ALTER table forum_node_tags ENABLE TRIGGER ALL;
+ALTER table forum_questionsubscription ENABLE TRIGGER ALL;
+ALTER table forum_vote ENABLE TRIGGER ALL;
+ALTER table forum_flag ENABLE TRIGGER ALL;
+ALTER table forum_badge ENABLE TRIGGER ALL;
+ALTER table forum_award ENABLE TRIGGER ALL;
+ALTER table forum_openidnonce ENABLE TRIGGER ALL;
+ALTER table forum_openidassociation ENABLE TRIGGER ALL;
+"""
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/exporter/exporter.py b/forum/modules/template_loader.py/forum_modules/exporter/exporter.py
new file mode 100644 (file)
index 0000000..c54e758
--- /dev/null
@@ -0,0 +1,515 @@
+import os, tarfile, datetime, logging, re, ConfigParser, shutil
+
+from django.core.cache import cache
+from django.utils.translation import ugettext as _
+from forum.models import *
+from forum.settings import APP_URL
+from forum.templatetags.extra_tags import diff_date
+import xml.etree.ElementTree
+from xml.etree import ElementTree as ET
+from xml.etree.ElementTree import Comment, _encode, ProcessingInstruction, QName, fixtag, _escape_attrib, _escape_cdata
+from forum import settings
+from django.conf import settings as djsettings
+import settings as selfsettings
+
+CACHE_KEY = "%s_exporter_state" % APP_URL
+EXPORT_STEPS = []
+
+TMP_FOLDER = os.path.join(os.path.dirname(__file__), 'tmp')
+LAST_BACKUP = os.path.join(TMP_FOLDER, 'backup.tar.gz')
+
+DATE_AND_AUTHOR_INF_SECTION = 'DateAndAuthor'
+OPTIONS_INF_SECTION = 'Options'
+META_INF_SECTION = 'Meta'
+
+DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
+DATE_FORMAT = "%Y-%m-%d"
+
+def Etree_pretty__write(self, file, node, encoding, namespaces,
+                        level=0, identator="    "):
+    tag = node.tag
+    if tag is Comment:
+        file.write(level * identator + "<!-- %s -->" % _escape_cdata(node.text, encoding))
+    elif tag is ProcessingInstruction:
+        file.write("<?%s?>" % _escape_cdata(node.text, encoding))
+    else:
+        items = node.items()
+        xmlns_items = [] # new namespaces in this scope
+        try:
+            if isinstance(tag, QName) or tag[:1] == "{":
+                tag, xmlns = fixtag(tag, namespaces)
+                if xmlns: xmlns_items.append(xmlns)
+        except TypeError:
+            raise #_raise_serialization_error(tag)
+        file.write("\n" + level * identator + "<" + _encode(tag, encoding))
+        if items or xmlns_items:
+            items.sort() # lexical order
+            for k, v in items:
+                try:
+                    if isinstance(k, QName) or k[:1] == "{":
+                        k, xmlns = fixtag(k, namespaces)
+                        if xmlns: xmlns_items.append(xmlns)
+                except TypeError:
+                    raise #_raise_serialization_error(k)
+                try:
+                    if isinstance(v, QName):
+                        v, xmlns = fixtag(v, namespaces)
+                        if xmlns: xmlns_items.append(xmlns)
+                except TypeError:
+                    raise #_raise_serialization_error(v)
+                file.write(u" %s=\"%s\"" % (_encode(k, encoding),
+                                            _escape_attrib(v, encoding)))
+            for k, v in xmlns_items:
+                file.write(u" %s=\"%s\"" % (_encode(k, encoding),
+                                            _escape_attrib(v, encoding)))
+        if node.text or len(node):
+            file.write(">")
+            if node.text:
+                file.write(_escape_cdata(node.text, encoding))
+            for n in node:
+                self._write(file, n, encoding, namespaces, level + 1, identator)
+            if node.text and len(node.text) < 125:
+                file.write("</" + _encode(tag, encoding) + ">")
+            else:
+                file.write("\n" + level * identator + "</" + _encode(tag, encoding) + ">")
+        else:
+            file.write(" />")
+        for k, v in xmlns_items:
+            del namespaces[v]
+    if node.tail:
+        file.write(_escape_cdata(node.tail.replace("\n", (level * identator )+ "\n"), encoding))
+
+def make_date(date, with_time=True):
+    try:
+        return date.strftime(with_time and DATETIME_FORMAT or DATE_FORMAT)
+    except ValueError, e:
+        return date.replace(year=1900).strftime(with_time and DATETIME_FORMAT or DATE_FORMAT)
+
+
+def ET_Element_add_tag(el, tag_name, content = None, **attrs):
+    tag = ET.SubElement(el, tag_name)
+
+    if content:
+        tag.text = unicode(content)
+
+    for k, v in attrs.items():
+        tag.set(k, unicode(v))
+
+    return tag
+
+GOOD_TAG_NAME = re.compile("^\w+$")
+
+def make_extra(el, v):
+    if v is None:
+        return
+
+
+    if isinstance(v, (int, long, str, unicode, float, bool, dict, list, tuple)):
+        if isinstance(v, tuple):
+            t = 'list'
+        else:
+            t = v.__class__.__name__
+    else:
+        t = 'unknown'
+
+    value = el.add('value', type=t)
+
+    if isinstance(v, (list, tuple)):
+        for i in v:
+            item = value.add('item')
+            make_extra(item, i)
+
+    elif isinstance(v, dict):
+        for k, i in v.items():
+            item = value.add('item', key=k)
+            make_extra(item, i)
+    else:
+        value.text = unicode(v)
+
+def write_to_file(root, tmp, filename):
+    tree = ET.ElementTree(root)
+    tree.write(os.path.join(tmp, filename), encoding='UTF-8')
+
+def create_targz(tmp, files, start_time, options, user, state, set_state):
+    if os.path.exists(LAST_BACKUP):
+        os.remove(LAST_BACKUP)
+        
+    t = tarfile.open(name=LAST_BACKUP, mode = 'w:gz')
+
+    state['overall']['status'] = _('Compressing xml files')
+    set_state()
+
+    for f in files:
+        t.add(os.path.join(tmp, f), arcname="/%s" % f)
+
+    if options.get('uplodaded_files', False):
+        state['overall']['status'] = _('Importing uploaded files')
+        set_state()
+        export_upfiles(t)
+
+    if options.get('import_skins_folder', False):
+        state['overall']['status'] = _('Importing skins folder')
+        set_state()
+        export_skinsfolder(t)
+
+    state['overall']['status'] = _('Writing inf file.')
+    set_state()
+
+    now = datetime.datetime.now()
+    domain = re.match('[\w-]+\.[\w-]+(\.[\w-]+)*', djsettings.APP_URL)
+    if domain:
+        domain = '_'.join(domain.get(0).split('.'))
+    else:
+        domain = 'localhost'
+
+    fname = "%s-%s" % (domain, now.strftime('%Y%m%d%H%M'))
+
+    inf = ConfigParser.SafeConfigParser()
+
+    inf.add_section(DATE_AND_AUTHOR_INF_SECTION)
+
+    inf.set(DATE_AND_AUTHOR_INF_SECTION, 'file-name', "%s.tar.gz" % fname)
+    inf.set(DATE_AND_AUTHOR_INF_SECTION, 'author', unicode(user.id))
+    inf.set(DATE_AND_AUTHOR_INF_SECTION, 'site', djsettings.APP_URL)
+    inf.set(DATE_AND_AUTHOR_INF_SECTION, 'started', start_time.strftime(DATETIME_FORMAT))
+    inf.set(DATE_AND_AUTHOR_INF_SECTION, 'finished', now.strftime(DATETIME_FORMAT))
+
+    inf.add_section(OPTIONS_INF_SECTION)
+    inf.set(OPTIONS_INF_SECTION, 'anon-data', str(options.get('anon_data', False)))
+    inf.set(OPTIONS_INF_SECTION, 'with-upfiles', str(options.get('uplodaded_files', False)))
+    inf.set(OPTIONS_INF_SECTION, 'with-skins', str(options.get('import_skins_folder', False)))
+
+    inf.add_section(META_INF_SECTION)
+
+    for id, s in state.items():
+        inf.set(META_INF_SECTION, id, str(s['count']))
+
+    with open(os.path.join(tmp, 'backup.inf'), 'wb') as inffile:
+        inf.write(inffile)
+
+    t.add(os.path.join(tmp, 'backup.inf'), arcname='backup.inf')
+    state['overall']['status'] = _('Saving backup file')
+    set_state()
+    t.close()
+    shutil.copyfile(LAST_BACKUP, os.path.join(selfsettings.EXPORTER_BACKUP_STORAGE, "%s.tar.gz" % fname))
+    shutil.copyfile(os.path.join(tmp, 'backup.inf'), os.path.join(selfsettings.EXPORTER_BACKUP_STORAGE, "%s.backup.inf" % fname))
+
+    
+
+def export_upfiles(tf):
+    folder = str(settings.UPFILES_FOLDER)
+
+    if os.path.exists(folder):
+        tf.add(folder, arcname='/upfiles')
+
+
+def export_skinsfolder(tf):
+    folder = djsettings.TEMPLATE_DIRS[0]
+
+    if os.path.exists(folder):
+        tf.add(folder, arcname='/skins')
+
+
+def export(options, user):
+    original__write = xml.etree.ElementTree.ElementTree._write
+    xml.etree.ElementTree.ElementTree._write = Etree_pretty__write
+    xml.etree.ElementTree._ElementInterface.add = ET_Element_add_tag
+
+    start_time = datetime.datetime.now()
+    tmp = TMP_FOLDER
+    anon_data = options.get('anon_data', False)
+
+    steps = [s for s in EXPORT_STEPS if not (anon_data and s['fn'].is_user_data())]
+
+    state = dict([(s['id'], {
+        'status': _('Queued'), 'count': s['fn'].count(start_time), 'parsed': 0
+    }) for s in steps] + [
+        ('overall', {
+            'status': _('Starting'), 'count': sum([s['fn'].count(start_time) for s in steps]), 'parsed': 0
+        })
+    ])
+
+    full_state = dict(running=True, state=state, time_started="")
+
+    def set_state():
+        full_state['time_started'] = diff_date(start_time)
+        cache.set(CACHE_KEY, full_state)
+
+    set_state()
+
+    def ping_state(name):
+        state[name]['parsed'] += 1
+        state['overall']['parsed'] += 1
+        set_state()
+
+    def run(fn, name):
+        def ping():
+            ping_state(name)
+
+        state['overall']['status'] = _('Exporting %s') % s['name']
+        state[name]['status'] = _('Exporting')
+
+        root, fname = fn(ping, start_time, anon_data)
+
+        state[name]['status'] = _('Writing temp file')
+        state['overall']['status'] = _('Writing %s temp file') % s['name']
+
+        set_state()
+
+        write_to_file(root, tmp, fname)
+        state[name]['status'] = _('Done')
+
+        set_state()
+
+        return fname
+
+    try:
+        dump_files = []
+
+        for s in steps:
+            dump_files.append(run(s['fn'], s['id']))
+
+        state['overall']['status'] = _('Compressing files')
+        set_state()
+
+        create_targz(tmp, dump_files, start_time, options, user, state, set_state)
+        full_state['running'] = False
+        full_state['errors'] = False
+        state['overall']['status'] = _('Done')
+
+        set_state()
+    except Exception, e:
+        full_state['running'] = False
+        full_state['errors'] = "%s: %s" % (e.__class__.__name__, unicode(e))
+        set_state()
+        
+        import traceback
+        logging.error("Error executing xml backup: \n %s" % (traceback.format_exc()))
+    finally:
+        xml.etree.ElementTree.ElementTree._write = original__write
+        del xml.etree.ElementTree._ElementInterface.add
+
+
+def exporter_step(queryset, root_tag_name, el_tag_name, name, date_lock=None, user_data=False):
+
+    def decorator(fn):
+        def qs(lock):
+            if date_lock:
+                return queryset.filter(**{"%s__lte" % date_lock: lock})
+            return queryset
+
+        def decorated(ping, lock, anon_data):
+            root = ET.Element(root_tag_name)
+
+            for item in qs(lock).order_by('id').select_related():
+                el = root.add(el_tag_name)
+                fn(item, el, anon_data)
+                ping()
+
+            return root, "%s.xml" % root_tag_name
+
+        def count(lock):
+            return qs(lock).count()
+
+        def is_user_data():
+            return user_data
+
+        decorated.count = count
+        decorated.is_user_data = is_user_data
+
+        EXPORT_STEPS.append(dict(id=root_tag_name, name=name, fn=decorated))
+
+        return decorated
+
+    return decorator
+
+@exporter_step(Tag.objects.all(), 'tags', 'tag', _('Tags'))
+def export_tags(t, el, anon_data):
+    el.add('name', t.name)
+    if not anon_data:
+        el.add('author', t.created_by.id)
+    el.add('used', t.used_count)
+
+
+@exporter_step(User.objects.all(), 'users', 'user', _('Users'), 'date_joined', True)
+def export_users(u, el, anon_data):
+    el.add('id', u.id)
+    el.add('username', u.username)
+    el.add('password', u.password)
+    el.add('email', u.email, validated=u.email_isvalid and 'true' or 'false')
+    el.add('reputation', u.reputation)
+    el.add('badges', bronze=u.bronze, silver=u.silver, gold=u.gold)
+    el.add('joindate', make_date(u.date_joined))
+    el.add('active', u.is_active and 'true' or 'false')
+
+    el.add('realname', u.real_name)
+    el.add('bio', u.about)
+    el.add('location', u.location)
+    el.add('website', u.website)
+    el.add('birthdate', u.date_of_birth and make_date(u.date_of_birth, with_time=False) or "")
+
+    roles = el.add('roles')
+
+    if u.is_superuser:
+        roles.add('role', 'superuser')
+
+    if u.is_staff:
+        roles.add('role', 'moderator')
+
+    auth = el.add('authKeys')
+    for a in u.auth_keys.all():
+        key = auth.add('key')
+        key.add('provider', a.provider)
+        key.add('key', a.key)
+
+
+    ss = u.subscription_settings
+
+    notify = el.add('notifications', enabled=ss.enable_notifications and 'true' or 'false')
+
+    notify.add('notify', **dict([(t, ss.__dict__.get(t, 'n') == 'i' and 'true' or 'false') for t in ['member_joins', 'new_question', 'new_question_watched_tags', 'subscribed_questions']]))
+
+    notify.add('autoSubscribe', **dict([(t, ss.__dict__.get(t, False) and 'true' or 'false') for t in [
+            'all_questions', 'all_questions_watched_tags', 'questions_asked', 'questions_answered', 'questions_commented', 'questions_viewed']]))
+
+    notify.add('notifyOnSubscribed', **dict([(t, ss.__dict__.get("notify_%s" % t, False) and 'true' or 'false') for t in [
+            'answers', 'reply_to_comments', 'comments_own_post', 'comments', 'accepted']]))
+
+    notify.add('digest', ss.send_digest and 'on' or 'off')
+
+    watched = el.add('watchedTags')
+    rejected = el.add('rejectedTags')
+
+    for m in u.tag_selections.all():
+        if m.reason == 'good':
+            watched.add('tag', m.tag.name)
+        else:
+            rejected.add('tag', m.tag.name)
+
+    
+
+@exporter_step(Node.objects.all(), 'nodes', 'node', _('Nodes'), 'added_at')
+def export_nodes(n, el, anon_data):
+    el.add('id', n.id)
+    el.add('type', n.node_type)
+
+    if not anon_data:
+        el.add('author', n.author.id)
+    el.add('date', make_date(n.added_at))
+    el.add('parent', n.parent and n.parent.id or "")
+    el.add('absparent', n.abs_parent and n.abs_parent or "")
+
+    act = el.add('lastactivity')
+    act.add('by', n.last_activity_by and n.last_activity_by.id or "")
+    act.add('at', n.last_activity_at and make_date(n.last_activity_at) or "")
+
+    el.add('title', n.title)
+    el.add('body', n.body)
+
+    el.add('score', n.score)
+
+    tags = el.add('tags')
+
+    for t in n.tagname_list():
+        tags.add('tag', t)
+
+    try:
+        active = n.active_revision and n.active_revision.revision or n.revisions.order_by('revision')[0].revision
+    except IndexError:
+        active = 0
+
+    revs = el.add('revisions', active=active)
+
+    for r in n.revisions.order_by('revision'):
+        rev = revs.add('revision')
+        rev.add('number', r.revision)
+        rev.add('summary', r.summary)
+        if not anon_data:
+            rev.add('author', r.author.id)
+        rev.add('date', make_date(r.revised_at))
+
+        rev.add('title', r.title)
+        rev.add('body', r.body)
+        rev.add('tags', ", ".join(r.tagname_list()))
+
+    el.add('marked', n.marked and 'true' or 'false')
+    el.add('extraRef', n.extra_ref and n.extra_ref.id or "")
+    make_extra(el.add('extraData'), n.extra)
+    el.add('extraCount', n.extra_count and n.extra_count or "")
+
+
+@exporter_step(Action.objects.all(), 'actions', 'action', _('Actions'), 'action_date')
+def export_actions(a, el, anon_data):
+    el.add('id', a.id)
+    el.add('type', a.action_type)
+    el.add('date', make_date(a.action_date))
+
+    if not anon_data:
+        el.add('user', a.user.id)
+        el.add('realUser', a.real_user and a.real_user.id or "")
+        el.add('ip', a.ip)
+    el.add('node', a.node and a.node.id or "")
+
+    make_extra(el.add('extraData'), a.extra)
+
+    canceled = el.add('canceled', state=a.canceled and 'true' or 'false')
+
+    if a.canceled:
+        if not anon_data:
+            canceled.add('user', a.canceled_by.id)
+            canceled.add('ip', a.canceled_ip)
+
+        canceled.add('date', make_date(a.canceled_at))        
+
+    if not anon_data:
+        reputes = el.add('reputes')
+
+        for r in a.reputes.all():
+            repute = reputes.add('repute', byCanceled=r.by_canceled and 'true' or 'false')
+            repute.add('user', r.user.id)
+            repute.add('value', r.value)
+
+
+#@exporter_step(NodeState.objects.all(), 'states', 'state', _('Node states'), 'action__action_date')
+#def export_states(s, el, anon_data):
+#    el.add('type', s.state_type)
+#    el.add('node', s.node.id)
+#    el.add('trigger', s.action.id)
+
+
+#@exporter_step(Badge.objects.all(), 'badges', 'badge', _('Badges'), user_data=True)
+#def export_badges(b, el, anon_data):
+#    el.add('type', ["", 'gold', 'silver', 'bronze'][b.type])
+#    el.add('name', b.cls)
+#    el.add('count', b.awarded_count)
+
+
+@exporter_step(Award.objects.all(), 'awards', 'award', _('Awards'), 'awarded_at', True)
+def export_awards(a, el, anon_data):
+    el.add('badge', a.badge.cls)
+    el.add('user', a.user.id)
+    el.add('node', a.node and a.node.id or "")
+    el.add('trigger', a.trigger and a.trigger.id or "")
+    el.add('action', a.action.id)
+
+@exporter_step(KeyValue.objects.all(), 'settings', 'setting', _('Settings'))
+def export_settings(s, el, anon_data):
+    el.add('key', s.key)
+    make_extra(el.add('value'), s.value)
+
+
+
+
+
+
+
+
+        
+
+
+
+
+
+
+
+
diff --git a/forum/modules/template_loader.py/forum_modules/exporter/forms.py b/forum/modules/template_loader.py/forum_modules/exporter/forms.py
new file mode 100644 (file)
index 0000000..464712d
--- /dev/null
@@ -0,0 +1,8 @@
+from django import forms
+from django.utils.translation import ugettext as _
+
+class ExporterForm(forms.Form):
+    anon_data = forms.BooleanField(label=_('Anonymized data'), help_text=_('Don\'t export user data and make all content anonymous'), required=False)
+    uplodaded_files = forms.BooleanField(label=_('Uploaded files'), help_text=_('Include uploaded files in the backup'), required=False, initial=True)
+    import_skins_folder = forms.BooleanField(label=_('Skins folder'), help_text=_('Include skins folder in the backup'), required=False, initial=False)
+    
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/exporter/importer.py b/forum/modules/template_loader.py/forum_modules/exporter/importer.py
new file mode 100644 (file)
index 0000000..2fd72e9
--- /dev/null
@@ -0,0 +1,665 @@
+import os, tarfile, datetime, ConfigParser, logging
+
+from django.utils.translation import ugettext as _
+from django.core.cache import cache
+
+from south.db import db
+
+from xml.sax import make_parser
+from xml.sax.handler import ContentHandler, ErrorHandler
+
+from forum.templatetags.extra_tags import diff_date
+
+from exporter import TMP_FOLDER, DATETIME_FORMAT, DATE_FORMAT, META_INF_SECTION, CACHE_KEY
+from orm import orm
+import commands, settings
+
+NO_DEFAULT = object()
+
+import string
+
+class SafeReader():
+    def __init__(self, loc):
+        self.base = open(loc)
+
+    def read(self, *args):
+        return "".join(c for c in self.base.read(*args) if c in string.printable)
+
+    def readLine(self, *args):
+        return "".join(c for c in self.base.readLine(*args) if c in string.printable)
+
+    def close(self):
+        self.base.close()
+
+
+class ContentElement():
+    def __init__(self, content):
+        self._content = content
+
+    def content(self):
+        return self._content.strip()
+
+    def as_bool(self):
+        return self.content() == "true"
+
+    def as_date(self, default=NO_DEFAULT):
+        try:
+            return datetime.datetime.strptime(self.content(), DATE_FORMAT)
+        except:
+            if default == NO_DEFAULT:
+                return datetime.date.fromtimestamp(0)
+            else:
+                return default
+            
+
+    def as_datetime(self, default=NO_DEFAULT):
+        try:
+            return datetime.datetime.strptime(self.content(), DATETIME_FORMAT)
+        except:
+            if default == NO_DEFAULT:
+                return datetime.datetime.fromtimestamp(0)
+            else:
+                return default
+
+    def as_int(self, default=0):
+        try:
+            return int(self.content())
+        except:
+            return default
+
+    def __str__(self):
+        return self.content()
+
+
+class RowElement(ContentElement):
+    def __init__(self, name, attrs, parent=None):
+        self.name = name.lower()
+        self.parent = parent
+        self.attrs = dict([(k.lower(), ContentElement(v)) for k, v in attrs.items()])
+        self._content = u''
+        self.sub_elements = {}
+
+        if parent:
+            parent.add(self)
+
+    def add_to_content(self, ch):
+        self._content += unicode(ch)
+
+    def add(self, sub):
+        curr = self.sub_elements.get(sub.name, None)
+
+        if not curr:
+            curr = []
+            self.sub_elements[sub.name] = curr
+
+        curr.append(sub)
+
+    def get(self, name, default=None):
+        return self.sub_elements.get(name.lower(), [default])[-1]
+
+    def get_list(self, name):
+        return self.sub_elements.get(name.lower(), [])
+
+    def get_listc(self, name):
+        return [r.content() for r in self.get_list(name)]
+
+    def getc(self, name, default=""):
+        el = self.get(name, None)
+
+        if el:
+            return el.content()
+        else:
+            return default
+
+    def get_attr(self, name, default=""):
+        return self.attrs.get(name.lower(), default)
+
+    def as_pickled(self, default=None):
+        value_el = self.get('value')
+
+        if value_el:
+            return value_el._as_pickled(default)
+        else:
+            return default
+
+    TYPES_MAP = dict([(c.__name__, c) for c in (int, long, str, unicode, float)])
+
+    def _as_pickled(self, default=None):
+        type = self.get_attr('type').content()
+
+        try:
+            if type == 'dict':
+                return dict([ (item.get_attr('key'), item.as_pickled()) for item in self.get_list('item') ])
+            elif type == 'list':
+                return [item.as_pickled() for item in self.get_list('item')]
+            elif type == 'bool':
+                return self.content().lower() == 'true'
+            elif type in RowElement.TYPES_MAP:
+                return RowElement.TYPES_MAP[type](self.content())
+            else:
+                return self.content()
+        except:
+            return default
+
+
+
+
+class TableHandler(ContentHandler):
+    def __init__(self, root_name, row_name, callback, callback_args = [], ping = None):
+        self.root_name = root_name.lower()
+        self.row_name = row_name.lower()
+        self.callback = callback
+        self.callback_args = callback_args
+        self.ping = ping
+
+        self._reset()
+
+    def _reset(self):
+        self.curr_element = None
+        self.in_tag = None
+
+    def startElement(self, name, attrs):
+        name = name.lower()
+
+        if name == self.root_name.lower():
+            pass
+        elif name == self.row_name:
+            self.curr_element = RowElement(name, attrs)
+        else:
+            self.curr_element = RowElement(name, attrs, self.curr_element)
+
+    def characters(self, ch):
+        if self.curr_element:
+            self.curr_element.add_to_content(ch)
+
+    def endElement(self, name):
+        name = name.lower()
+
+        if name == self.root_name:
+            pass
+        elif name == self.row_name:
+            self.callback(self.curr_element, *self.callback_args)
+            if self.ping:
+                self.ping()
+
+            self._reset()
+        else:
+            self.curr_element = self.curr_element.parent
+
+
+class SaxErrorHandler(ErrorHandler):
+    def error(self, e):
+        raise e
+
+    def fatalError(self, e):
+        raise e
+
+    def warning(self, e):
+        raise e
+
+def disable_triggers():
+    if db.backend_name == "postgres":
+        db.start_transaction()
+        db.execute_many(commands.PG_DISABLE_TRIGGERS)
+        db.commit_transaction()
+
+def enable_triggers():
+    if db.backend_name == "postgres":
+        db.start_transaction()
+        db.execute_many(commands.PG_ENABLE_TRIGGERS)
+        db.commit_transaction()
+
+def reset_sequences():
+    if db.backend_name == "postgres":
+        db.start_transaction()
+        db.execute_many(commands.PG_SEQUENCE_RESETS)
+        db.commit_transaction()
+
+def reset_fts_indexes():
+    pass
+
+FILE_HANDLERS = []
+
+def start_import(fname, tag_merge, user):
+
+    start_time = datetime.datetime.now()
+    steps = [s for s in FILE_HANDLERS]
+
+    with open(os.path.join(TMP_FOLDER, 'backup.inf'), 'r') as inffile:
+        inf = ConfigParser.SafeConfigParser()
+        inf.readfp(inffile)
+
+        state = dict([(s['id'], {
+            'status': _('Queued'), 'count': int(inf.get(META_INF_SECTION, s['id'])), 'parsed': 0
+        }) for s in steps] + [
+            ('overall', {
+                'status': _('Starting'), 'count': int(inf.get(META_INF_SECTION, 'overall')), 'parsed': 0
+            })
+        ])
+
+    full_state = dict(running=True, state=state, time_started="")
+
+    def set_state():
+        full_state['time_started'] = diff_date(start_time)
+        cache.set(CACHE_KEY, full_state)
+
+    set_state()
+
+    def ping_state(name):
+        state[name]['parsed'] += 1
+        state['overall']['parsed'] += 1
+        set_state()
+
+    data = {
+        'is_merge': True,
+        'tag_merge': tag_merge
+    }
+
+    def run(fn, name):
+        def ping():
+            ping_state(name)
+
+        state['overall']['status'] = _('Importing %s') % s['name']
+        state[name]['status'] = _('Importing')
+
+
+        fn(TMP_FOLDER, user, ping, data)
+
+        state[name]['status'] = _('Done')
+
+        set_state()
+
+        return fname
+
+    #dump = tarfile.open(fname, 'r')
+    #dump.extractall(TMP_FOLDER)
+
+    try:
+
+        disable_triggers()
+        db.start_transaction()
+
+        for h in FILE_HANDLERS:
+            run(h['fn'], h['id'])
+
+        db.commit_transaction()
+        enable_triggers()
+
+        settings.MERGE_MAPPINGS.set_value(dict(merged_nodes=data['nodes_map'], merged_users=data['users_map']))
+
+        reset_sequences()
+    except Exception, e:
+        full_state['running'] = False
+        full_state['errors'] = "%s: %s" % (e.__class__.__name__, unicode(e))
+        set_state()
+
+        import traceback
+        logging.error("Error executing xml import: \n %s" % (traceback.format_exc()))
+
+def file_handler(file_name, root_tag, el_tag, name, args_handler=None, pre_callback=None, post_callback=None):
+    def decorator(fn):
+        def decorated(location, current_user, ping, data):
+            if pre_callback:
+                pre_callback(current_user, data)
+
+            if (args_handler):
+                args = args_handler(current_user, data)
+            else:
+                args = []
+
+            parser = make_parser()
+            handler = TableHandler(root_tag, el_tag, fn, args, ping)
+            parser.setContentHandler(handler)
+            #parser.setErrorHandler(SaxErrorHandler())
+
+            parser.parse(SafeReader(os.path.join(location, file_name)))
+
+            if post_callback:
+                post_callback()
+
+        FILE_HANDLERS.append(dict(id=root_tag, name=name, fn=decorated))
+        return decorated
+    return decorator
+
+def verify_existence(row):
+    try:
+        return orm.User.objects.get(email=row.getc('email'))
+    except:
+        for key in row.get('authKeys').get_list('key'):
+            key = key=key.getc('key')
+
+            if not ("google.com" in key or "yahoo.com" in key):
+                try:
+                    return orm.AuthKeyUserAssociation.objects.get(key=key).user
+                except:
+                    pass
+
+    return None
+
+def user_import_pre_callback(user, data):
+    data['users_map'] = {}
+
+@file_handler('users.xml', 'users', 'user', _('Users'), pre_callback=user_import_pre_callback, args_handler=lambda u, d: [u, d['is_merge'], d['users_map']])
+def user_import(row, current_user, is_merge, users_map):
+    existent = is_merge and verify_existence(row) or None
+
+    roles = row.get('roles').get_listc('role')
+    valid_email = row.get('email').get_attr('validated').as_bool()
+    badges = row.get('badges')
+
+    if existent:
+        user = existent
+
+        user.reputation += row.get('reputation').as_int()
+        user.gold += badges.get_attr('gold').as_int()
+        user.silver += badges.get_attr('gold').as_int()
+        user.bronze += badges.get_attr('gold').as_int()
+
+    else:
+        username = row.getc('username')
+
+        if is_merge:
+            username_count = 0
+
+            while orm.User.objects.filter(username=username).count():
+                username_count += 1
+                username = "%s %s" % (row.getc('username'), username_count)
+
+        user = orm.User(
+                id           = (not is_merge) and row.getc('id') or None,
+                username     = username,
+                password     = row.getc('password'),
+                email        = row.getc('email'),
+                email_isvalid= valid_email,
+                is_superuser = (not is_merge) and 'superuser' in roles,
+                is_staff     = ('moderator' in roles) or (is_merge and 'superuser' in roles),
+                is_active    = row.get('active').as_bool(),
+                date_joined  = row.get('joindate').as_datetime(),
+                about         = row.getc('bio'),
+                date_of_birth = row.get('birthdate').as_date(None),
+                website       = row.getc('website'),
+                reputation    = row.get('reputation').as_int(),
+                gold          = badges.get_attr('gold').as_int(),
+                silver        = badges.get_attr('silver').as_int(),
+                bronze        = badges.get_attr('bronze').as_int(),
+                real_name     = row.getc('realname'),
+                location      = row.getc('location'),
+        )
+
+    user.save()
+
+    users_map[row.get('id').as_int()] = user.id
+
+    authKeys = row.get('authKeys')
+
+    for key in authKeys.get_list('key'):
+        if (not is_merge) or orm.AuthKeyUserAssociation.objects.filter(key=key.getc('key')).count() == 0:
+            orm.AuthKeyUserAssociation(user=user, key=key.getc('key'), provider=key.getc('provider')).save()
+
+    if not existent:
+        notifications = row.get('notifications')
+
+        attributes = dict([(str(k), v.as_bool() and 'i' or 'n') for k, v in notifications.get('notify').attrs.items()])
+        attributes.update(dict([(str(k), v.as_bool()) for k, v in notifications.get('autoSubscribe').attrs.items()]))
+        attributes.update(dict([(str("notify_%s" % k), v.as_bool()) for k, v in notifications.get('notifyOnSubscribed').attrs.items()]))
+
+        ss = orm.SubscriptionSettings(user=user, enable_notifications=notifications.get_attr('enabled').as_bool(), **attributes)
+
+        if current_user.id == row.get('id').as_int():
+            ss.id = current_user.subscription_settings.id
+
+        ss.save()
+        
+
+def pre_tag_import(user, data):
+    data['tag_mappings'] = dict([ (t.name, t) for t in orm.Tag.objects.all() ])
+
+
+@file_handler('tags.xml', 'tags', 'tag', _('Tags'), pre_callback=pre_tag_import, args_handler=lambda u, d: [d['is_merge'], d['tag_merge'], d['users_map'], d['tag_mappings']])
+def tag_import(row, is_merge, tag_merge, users_map, tag_mappings):
+    created_by = row.get('used').as_int()
+    created_by = users_map.get(created_by, created_by)
+
+    tag_name = row.getc('name')
+    tag_name = tag_merge and tag_merge.get(tag_name, tag_name) or tag_name
+
+    if is_merge and tag_name in tag_mappings:
+        tag = tag_mappings[tag_name]
+        tag.used_count += row.get('used').as_int()
+    else:
+        tag = orm.Tag(name=tag_name, used_count=row.get('used').as_int(), created_by_id=created_by)
+        tag_mappings[tag.name] = tag
+
+    tag.save()
+
+def pre_node_import(user, data):
+    data['nodes_map'] = {}
+
+@file_handler('nodes.xml', 'nodes', 'node', _('Nodes'), pre_callback=pre_node_import,
+              args_handler=lambda u, d: [d['is_merge'], d['tag_merge'], d['tag_mappings'], d['nodes_map'], d['users_map']])
+def node_import(row, is_merge, tag_merge, tags, nodes_map, users_map):
+
+    ntags = []
+
+    for t in row.get('tags').get_list('tag'):
+        t = t.content()
+        ntags.append(tags[tag_merge and tag_merge.get(t, t) or t])
+
+    author = row.get('author').as_int()
+
+    last_act = row.get('lastactivity')
+    last_act_user = last_act.get('by').as_int(None)
+
+    parent = row.get('parent').as_int(None)
+    abs_parent = row.get('absparent').as_int(None)
+
+    node = orm.Node(
+            id            = (not is_merge) and row.getc('id') or None,
+            node_type     = row.getc('type'),
+            author_id     = users_map.get(author, author),
+            added_at      = row.get('date').as_datetime(),
+            parent_id     = nodes_map.get(parent, parent),
+            abs_parent_id = nodes_map.get(abs_parent, abs_parent),
+            score         = row.get('score').as_int(0),
+
+            last_activity_by_id = last_act_user and users_map.get(last_act_user, last_act_user) or last_act_user,
+            last_activity_at    = last_act.get('at').as_datetime(None),
+
+            title         = row.getc('title'),
+            body          = row.getc('body'),
+            tagnames      = " ".join([t.name for t in ntags]),
+
+            marked        = row.get('marked').as_bool(),
+            extra_ref_id  = row.get('extraRef').as_int(None),
+            extra_count   = row.get('extraCount').as_int(0),
+            extra         = row.get('extraData').as_pickled()
+    )
+
+    node.save()
+
+    nodes_map[row.get('id').as_int()] = node.id
+
+    node.tags = ntags
+
+    revisions = row.get('revisions')
+    active = revisions.get_attr('active').as_int()
+
+    if active == 0:
+        active = orm.NodeRevision(
+            author_id = node.author_id,
+            body = row.getc('body'),
+            node = node,
+            revised_at = row.get('date').as_datetime(),
+            revision = 1,
+            summary = _('Initial revision'),
+            tagnames = " ".join([t.name for t in ntags]),
+            title = row.getc('title'),
+        )
+
+        active.save()
+    else:
+        for r in revisions.get_list('revision'):
+            author = row.get('author').as_int()
+
+            rev = orm.NodeRevision(
+                author_id = users_map.get(author, author),
+                body = r.getc('body'),
+                node = node,
+                revised_at = r.get('date').as_datetime(),
+                revision = r.get('number').as_int(),
+                summary = r.getc('summary'),
+                tagnames = " ".join(r.getc('tags').split(',')),
+                title = r.getc('title'),
+            )
+
+            rev.save()
+            if rev.revision == active:
+                active = rev
+
+    node.active_revision = active
+    node.save()
+
+POST_ACTION = {}
+
+def post_action(*types):
+    def decorator(fn):
+        for t in types:
+            POST_ACTION[t] = fn
+        return fn
+    return decorator
+
+def pre_action_import_callback(user, data):
+    data['actions_map'] = {}
+
+def post_action_import_callback():
+    with_state = orm.Node.objects.filter(id__in=orm.NodeState.objects.values_list('node_id', flat=True).distinct())
+
+    for n in with_state:
+        n.state_string = "".join(["(%s)" % s for s in n.states.values_list('state_type')])
+        n.save()
+
+@file_handler('actions.xml', 'actions', 'action', _('Actions'), post_callback=post_action_import_callback,
+              pre_callback=pre_action_import_callback, args_handler=lambda u, d: [d['nodes_map'], d['users_map'], d['actions_map']])
+def actions_import(row, nodes, users, actions_map):
+    node = row.get('node').as_int(None)
+    user = row.get('user').as_int()
+    real_user = row.get('realUser').as_int(None)
+
+    action = orm.Action(
+        #id           = row.get('id').as_int(),
+        action_type  = row.getc('type'),
+        action_date  = row.get('date').as_datetime(),
+        node_id      = nodes.get(node, node),
+        user_id      = users.get(user, user),
+        real_user_id = users.get(real_user, real_user),
+        ip           = row.getc('ip'),
+        extra        = row.get('extraData').as_pickled(),
+    )
+
+    canceled = row.get('canceled')
+    if canceled.get_attr('state').as_bool():
+        by = canceled.get('user').as_int()
+        action.canceled = True
+        action.canceled_by_id = users.get(by, by)
+        action.canceled_at = canceled.getc('date') #.as_datetime(),
+        action.canceled_ip = canceled.getc('ip')
+
+    action.save()
+
+    actions_map[row.get('id').as_int()] = action.id
+
+    for r in row.get('reputes').get_list('repute'):
+        by_canceled = r.get_attr('byCanceled').as_bool()
+
+        orm.ActionRepute(
+            action = action,
+            user_id = users[r.get('user').as_int()],
+            value = r.get('value').as_int(),
+
+            date = by_canceled and action.canceled_at or action.action_date,
+            by_canceled = by_canceled
+        ).save()
+
+    if (not action.canceled) and (action.action_type in POST_ACTION):
+        POST_ACTION[action.action_type](row, action, users, nodes, actions_map)
+
+
+
+
+# Record of all persisted votes.
+persisted_votes = []
+@post_action('voteup', 'votedown', 'voteupcomment')
+def vote_action(row, action, users, nodes, actions):
+    # Check to see if the vote has already been registered.
+    if not (action.user_id, action.node_id) in persisted_votes:
+        # Persist the vote action.
+        orm.Vote(user_id=action.user_id, node_id=action.node_id, action=action,
+                 voted_at=action.action_date, value=(action.action_type != 'votedown') and 1 or -1).save()
+
+        # Record the vote action.  This will help us avoid duplicates.
+        persisted_votes.append((action.user_id, action.node_id))
+
+
+def state_action(state):
+    def fn(row, action, users, nodes, actions):
+        if orm.NodeState.objects.filter(state_type = state, node = action.node_id).count():
+            return
+
+        orm.NodeState(
+            state_type = state,
+            node_id = action.node_id,
+            action = action
+        ).save()
+    return fn
+
+post_action('wikify')(state_action('wiki'))
+post_action('delete')(state_action('deleted'))
+post_action('acceptanswer')(state_action('accepted'))
+post_action('publish')(state_action('published'))
+
+
+@post_action('flag')
+def flag_action(row, action, users, nodes, actions):
+    orm.Flag(user_id=action.user_id, node_id=action.node_id, action=action, reason=action.extra or "").save()
+
+
+def award_import_args(user, data):
+    return [ dict([ (b.cls, b) for b in orm.Badge.objects.all() ]) , data['nodes_map'], data['users_map'], data['actions_map']]
+
+
+@file_handler('awards.xml', 'awards', 'award', _('Awards'), args_handler=award_import_args)
+def awards_import(row, badges, nodes, users, actions):
+    badge_type = badges.get(row.getc('badge'), None)
+
+    if not badge_type:
+        return
+
+    action = row.get('action').as_int(None)
+    trigger = row.get('trigger').as_int(None)
+    node = row.get('node').as_int(None)
+    user = row.get('user').as_int()
+
+    if orm.Award.objects.filter(badge=badges[row.getc('badge')], user=users.get(user, user), node=nodes.get(node, node)).count():
+        return
+
+    award = orm.Award(
+        user_id = users.get(user, user),
+        badge = badge_type,
+        node_id = nodes.get(node, node),
+        action_id = actions.get(action, action),
+        trigger_id = actions.get(trigger, trigger)
+    ).save()
+
+
+#@file_handler('settings.xml', 'settings', 'setting', _('Settings'))
+def settings_import(row):
+    orm.KeyValue(key=row.getc('key'), value=row.get('value').as_pickled())
+
+
+
+
+
+
+
+
+    
diff --git a/forum/modules/template_loader.py/forum_modules/exporter/mappings.py b/forum/modules/template_loader.py/forum_modules/exporter/mappings.py
new file mode 100644 (file)
index 0000000..a356dde
--- /dev/null
@@ -0,0 +1,27 @@
+from django.http import HttpResponseRedirect, HttpResponse, Http404, HttpResponsePermanentRedirect
+from django.template.defaultfilters import slugify
+
+from forum.views import readers
+from forum.modules import decorate
+from forum.models import Question
+
+import settings, logging
+
+@decorate(readers.question, needs_origin=True)
+def match_question_slug(origin, request, id, slug='', answer=None):
+    try:
+        id = int(id)
+    except:
+        raise Http404()
+
+    if settings.MERGE_MAPPINGS and (int(id) in settings.MERGE_MAPPINGS.get('merged_nodes', {})):
+        try:
+            question = Question.objects.get(id=id)
+
+            if slug != slugify(question.title):
+                return origin(request, settings.MERGE_MAPPINGS['merged_nodes'][int(id)], slug, answer)
+
+        except:
+            pass
+
+    return origin(request, id, slug, answer)
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/exporter/orm.py b/forum/modules/template_loader.py/forum_modules/exporter/orm.py
new file mode 100644 (file)
index 0000000..ff23c85
--- /dev/null
@@ -0,0 +1,265 @@
+from south.v2 import DataMigration\r
+from south.orm import FakeORM\r
+\r
+class Migration(DataMigration):\r
+    def forwards(self, orm):\r
+        pass\r
+\r
+\r
+    def backwards(self, orm):\r
+        "Write your backwards methods here."\r
+\r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.action': {\r
+            'Meta': {'object_name': 'Action'},\r
+            'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),\r
+            'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'real_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'proxied_actions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.actionrepute': {\r
+            'Meta': {'object_name': 'ActionRepute'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}),\r
+            'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('user', 'badge', 'node'),)", 'object_name': 'Award'},\r
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'award'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.Badge']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'trigger': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'object_name': 'Badge'},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'symmetrical': 'False', 'through': "orm['forum.Award']", 'to': "orm['forum.User']"}),\r
+            'cls': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.flag': {\r
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Flag'},\r
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'flag'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flags'", 'to': "orm['forum.Node']"}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flags'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}),\r
+            'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'state_string': ('django.db.models.fields.TextField', [], {'default': "''"}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'symmetrical': 'False', 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.nodestate': {\r
+            'Meta': {'unique_together': "(('node', 'state_type'),)", 'object_name': 'NodeState'},\r
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'node_state'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'states'", 'to': "orm['forum.Node']"}),\r
+            'state_type': ('django.db.models.fields.CharField', [], {'max_length': '16'})\r
+        },\r
+        'forum.openidassociation': {\r
+            'Meta': {'object_name': 'OpenIdAssociation'},\r
+            'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}),\r
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'issued': ('django.db.models.fields.IntegerField', [], {}),\r
+            'lifetime': ('django.db.models.fields.IntegerField', [], {}),\r
+            'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}),\r
+            'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'})\r
+        },\r
+        'forum.openidnonce': {\r
+            'Meta': {'object_name': 'OpenIdNonce'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),\r
+            'timestamp': ('django.db.models.fields.IntegerField', [], {})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 7, 1, 13, 6, 46, 789996)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'send_digest': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag'},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'symmetrical': 'False', 'through': "orm['forum.MarkedTag']", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'symmetrical': 'False', 'through': "orm['forum.QuestionSubscription']", 'to': "orm['forum.Node']"}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.userproperty': {\r
+            'Meta': {'unique_together': "(('user', 'key'),)", 'object_name': 'UserProperty'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'properties'", 'to': "orm['forum.User']"}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 7, 2, 13, 6, 46, 883626)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Vote'},\r
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'vote'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+\r
+    complete_apps = ['forum']\r
+\r
+orm = FakeORM(Migration, "forum")\r
+\r
diff --git a/forum/modules/template_loader.py/forum_modules/exporter/settings.py b/forum/modules/template_loader.py/forum_modules/exporter/settings.py
new file mode 100644 (file)
index 0000000..a37cd1b
--- /dev/null
@@ -0,0 +1,13 @@
+import os
+
+from django.conf import settings as djsettings
+from forum.settings.base import Setting, SettingSet
+from django.utils.translation import ugettext_lazy as _
+
+EXPORTER_SET = SettingSet('exporter', _('Exporter settings'), _("Data export settings"), 800)
+
+EXPORTER_BACKUP_STORAGE = Setting('EXPORTER_BACKUP_STORAGE', os.path.join(os.path.dirname(__file__), 'backups'), EXPORTER_SET, dict(
+label = _("Backups storage"),
+help_text = _("A folder to keep your backups organized.")))
+
+MERGE_MAPPINGS = Setting('MERGE_MAPPINGS', {})
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/exporter/startup.py b/forum/modules/template_loader.py/forum_modules/exporter/startup.py
new file mode 100644 (file)
index 0000000..e180097
--- /dev/null
@@ -0,0 +1,2 @@
+import views
+import mappings
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/exporter/templates/exporter.html b/forum/modules/template_loader.py/forum_modules/exporter/templates/exporter.html
new file mode 100644 (file)
index 0000000..78c12c7
--- /dev/null
@@ -0,0 +1,33 @@
+{% extends basetemplate %}
+
+{% load i18n %}
+
+{% block subtitle %}
+    {% trans "XML data exporter" %}
+{% endblock %}
+{% block description %}
+    {% trans "Export database to XML format" %}
+{% endblock %}
+
+{% block admincontent %}
+<p>
+    <strong>{% trans "Available backups" %}</strong>
+</p>
+<ul>
+    {% for b in available %}
+    <li>
+        {{ b.date }} by {{ b.author }}
+    </li>
+    {% endfor %}
+</ul>
+
+<p>
+    <strong>{% trans "Start new backup" %}</strong>
+</p>
+<form method="POST" action="">
+    <table>
+    {{ form.as_table }}
+    </table>
+    <input type="submit" name="start" value="{% trans "Start" %}" />
+</form>
+{% endblock %}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/exporter/templates/importer.html b/forum/modules/template_loader.py/forum_modules/exporter/templates/importer.html
new file mode 100644 (file)
index 0000000..d3fd942
--- /dev/null
@@ -0,0 +1,14 @@
+{% extends basetemplate %}
+
+{% load i18n %}
+
+{% block subtitle %}
+    {% trans "XML data importer" %}
+{% endblock %}
+{% block description %}
+    {% trans "Import data from dump file" %}
+{% endblock %}
+
+{% block admincontent %}
+
+{% endblock %}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/exporter/templates/running.html b/forum/modules/template_loader.py/forum_modules/exporter/templates/running.html
new file mode 100644 (file)
index 0000000..5936dcb
--- /dev/null
@@ -0,0 +1,164 @@
+{% extends basetemplate %}
+
+{% load i18n %}
+
+{% block subtitle %}
+    {% ifequal mode "exporter" %}{% trans "XML data exporter" %}{% else %}{% trans "XML data importer" %}{% endifequal %}
+{% endblock %}
+{% block description %}
+    {% ifequal mode "exporter" %}{% trans "Export database to XML format" %}{% else %}{% trans "Restore data from a previouus export" %}{% endifequal %}
+{% endblock %}
+
+{% block adminjs %}
+    <style type="text/css">
+        .state_bar {
+            width:100%;
+            height: 20px;
+            border: 1px solid black;
+            margin-bottom: 15px;
+            position: relative;
+            background: #FDF;
+        }
+
+        .state_label {
+            margin-left: auto;
+            margin-right: auto;
+            z-index: 1000;
+            position: absolute;
+            left: 0px;
+            top: 0px;
+            width: 100%;
+            height: 100%;
+            text-align: center;
+        }
+
+        .progress {
+            position: absolute;
+            left: 0px;
+            top: 0px;
+            width: 0%;
+            height: 100%;
+            background: #DFF;
+            z-index: 0;
+        }
+
+        #download_link {
+            display: none;
+        }
+    </style>
+
+    <script type="text/javascript">
+    $(function() {
+        var exporting = {% ifequal mode "exporter" %}true{% else %}false{% endifequal %};
+
+        var state = null;
+
+        function set_state(name, data) {
+            var $bar = $('#state_' + name);
+
+            if (data[name] === undefined) {
+                $bar.find('.state_label').html('{% trans "Skiped" %}')
+            } else if (state == null || data[name] != state[name]) {
+                var width = $bar.width();
+
+                $bar.find('.state_parsed').html(data[name].parsed);
+                $bar.find('.state_count').html(data[name].count);
+                $bar.find('.state_status').html(data[name].status);
+
+                var rel_parse = data[name].parsed / data[name].count;
+
+                $bar.find('.state_percentage').html(parseInt(rel_parse * 100) + '%');
+                $bar.find('.progress').css('width', parseInt(rel_parse * width) + 'px')
+            }
+        }
+
+        function check_state() {
+            var done = false;
+
+             function callback(data) {
+                if (done) {
+                   return;
+                }
+                set_state('overall', data.state);
+                {% for s in steps %}
+                    set_state('{{ s.id }}', data.state);
+                {% endfor %}
+
+                $('#time_started').html(data.time_started);
+
+                state = data;
+
+                if (data.running) {
+                    check_state();
+                } else {
+                    if (data.errors == false) {
+                        if (exporting) {
+                            $('#wait_message').html('{% trans "Your backup is ready to be downloaded."%}');
+                            $('#download_link').slideDown();
+                        } else {
+                            $('#wait_message').html('{% trans "All data sucessfully imported."%}')
+                        }
+                    } else {
+                        var msg;
+                        if (exporting) {
+                            msg = '{% trans "An error has occurred during de export proccess"%}';
+                        } else {
+                            msg = '{% trans "An error has occurred during de import proccess"%}';
+                        }
+                        $('#wait_message').html(msg + ': ' + data.errors + '<br />' +
+                        '{% trans "Please check the log file for a full stack trace." %}')
+                    }
+                }
+
+                done = true;
+             }
+
+             window.setTimeout(function() {
+                if (!done) {
+                    done = true;
+                    check_state();
+                }
+             }, 1000);
+
+             $.getJSON('{% url exporter_state %}', callback);
+        }
+
+        check_state();
+    });
+    </script>
+{% endblock %}
+
+{% block admincontent %}
+    <p id="wait_message">
+        {% ifequal mode "exporter" %}
+            {% trans "Please wait while we prepare your backup file to download." %}
+        {% else %}
+            {% trans "Please wait while we import your data." %}
+        {% endifequal %} -
+        {% blocktrans %}
+            Started <span id="time_started"></span>
+        {% endblocktrans %}
+    </p>
+    <p id="download_link"><a href="{% url exporter_download %}">{% trans "Download file" %}</a></p>
+    <table style="width: 100%">
+        <tr>
+            <td colspan="2">
+                <div class="state_bar" id="state_overall">
+                    <div class="state_label"><span class="state_status"></span> ({% trans "Total progress" %}: <span class="state_percentage">0%</span>)</div>
+                    <div class="progress"></div>
+                </div>
+            </td>
+        </tr>
+        {% for s in steps %}
+        <tr>
+            <td>{{ s.name }}:</td>
+            <td width="100%">
+                <div class="state_bar" id="state_{{ s.id }}">
+                    <div class="state_label"><span class="state_status"></span> - </span><span class="state_parsed">0</span> {% trans " of " %} <span class="state_count">{% trans "unknown" %}</span> (<span class="state_percentage">0%</span>)</div>
+                    <div class="progress"></div>
+                </div>
+            </td>
+        </tr>
+        {% endfor %}
+    </table>
+{% endblock %}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/exporter/tmp/README b/forum/modules/template_loader.py/forum_modules/exporter/tmp/README
new file mode 100644 (file)
index 0000000..98be257
--- /dev/null
@@ -0,0 +1 @@
+keep this folder writable
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/exporter/urls.py b/forum/modules/template_loader.py/forum_modules/exporter/urls.py
new file mode 100644 (file)
index 0000000..e9b35aa
--- /dev/null
@@ -0,0 +1,11 @@
+from django.conf.urls.defaults import *
+from django.views.generic.simple import direct_to_template
+from django.utils.translation import ugettext as _
+
+from views import state, running, download
+
+urlpatterns = patterns('',
+    url(r'^%s%s%s$' % (_('admin/'), _('exporter/'), _('state/')),  state, name='exporter_state'),
+    url(r'^%s(?P<mode>\w+)/%s$' % (_('admin/'), _('running/')),  running, name='exporter_running'),
+    url(r'^%s%s%s$' % (_('admin/'), _('exporter/'), _('download/')),  download, name='exporter_download'),
+)
diff --git a/forum/modules/template_loader.py/forum_modules/exporter/views.py b/forum/modules/template_loader.py/forum_modules/exporter/views.py
new file mode 100644 (file)
index 0000000..3709037
--- /dev/null
@@ -0,0 +1,91 @@
+import os, tarfile, ConfigParser, datetime
+
+from StringIO import StringIO
+from django.http import HttpResponse, HttpResponseRedirect, Http404
+from django.utils.translation import ugettext as _
+from django.utils import simplejson
+from django.core.cache import cache
+from django.core.urlresolvers import reverse
+from forum.views.admin import admin_tools_page, admin_page
+from forum.models import User
+from forms import ExporterForm
+from threading import Thread
+import settings as selsettings
+from forum import settings
+
+from exporter import export, CACHE_KEY, EXPORT_STEPS, LAST_BACKUP, DATE_AND_AUTHOR_INF_SECTION, DATETIME_FORMAT
+from importer import start_import
+
+
+@admin_tools_page(_('exporter'), _('XML data export'))
+def exporter(request):
+    state = cache.get(CACHE_KEY)
+
+    if state and state['running']:
+        return HttpResponseRedirect(reverse('exporter_running', kwargs=dict(mode='exporter')))
+
+    if request.method == 'POST':
+        form = ExporterForm(request.POST)
+
+        if form.is_valid():
+            thread = Thread(target=export, args=[form.cleaned_data, request.user])
+            thread.setDaemon(True)
+            thread.start()
+
+            return HttpResponseRedirect(reverse('exporter_running', kwargs=dict(mode='exporter')))
+    else:
+        form = ExporterForm()
+
+    available = []
+
+    folder = unicode(selsettings.EXPORTER_BACKUP_STORAGE)
+
+    for f in os.listdir(folder):
+        if (not os.path.isdir(os.path.join(folder, f))) and f.endswith('.backup.inf'):
+            try:
+                with open(os.path.join(folder, f), 'r') as inffile:
+                    inf = ConfigParser.SafeConfigParser()
+                    inf.readfp(inffile)
+
+                    if inf.get(DATE_AND_AUTHOR_INF_SECTION, 'site') == settings.APP_URL and os.path.exists(
+                                    os.path.join(folder, inf.get(DATE_AND_AUTHOR_INF_SECTION, 'file-name'))):
+                        available.append({
+                            'author': User.objects.get(id=inf.get(DATE_AND_AUTHOR_INF_SECTION, 'author')),
+                            'date': datetime.datetime.strptime(inf.get(DATE_AND_AUTHOR_INF_SECTION, 'finished'), DATETIME_FORMAT)
+                        })
+            except Exception, e:
+                pass
+
+    return ('modules/exporter/exporter.html', {
+        'form': form,
+        'available': available,
+    })
+
+@admin_page
+def running(request, mode):
+    state = cache.get(CACHE_KEY)
+    if state is None:
+        return HttpResponseRedirect(reverse('admin_tools', args=[_('exporter')]))
+
+    return ('modules/exporter/running.html', {
+        'mode': mode,
+        'steps': EXPORT_STEPS
+    })
+
+def state(request):
+    return HttpResponse(simplejson.dumps(cache.get(CACHE_KEY)), mimetype="application/json")
+
+@admin_page
+def download(request):
+    fname = LAST_BACKUP
+
+    if not os.path.exists(fname):
+        raise Http404
+
+    response = HttpResponse(open(fname, 'rb').read(), content_type='application/x-gzip')
+    response['Content-Length'] = os.path.getsize(fname)
+    response['Content-Disposition'] = 'attachment; filename=backup.tar.gz'
+    return response
+
+
+
diff --git a/forum/modules/template_loader.py/forum_modules/facebookauth/__init__.py b/forum/modules/template_loader.py/forum_modules/facebookauth/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/forum/modules/template_loader.py/forum_modules/facebookauth/authentication.py b/forum/modules/template_loader.py/forum_modules/facebookauth/authentication.py
new file mode 100644 (file)
index 0000000..b19d794
--- /dev/null
@@ -0,0 +1,87 @@
+import hashlib
+from time import time
+from datetime import datetime
+from urllib import urlopen,  urlencode
+from forum.authentication.base import AuthenticationConsumer, ConsumerTemplateContext, InvalidAuthentication
+from django.utils.translation import ugettext as _
+
+import settings
+
+try:
+    from json import load as load_json
+except:
+    from django.utils.simplejson import JSONDecoder
+
+    def load_json(json):
+        decoder = JSONDecoder()
+        return decoder.decode(json.read())
+
+REST_SERVER = 'http://api.facebook.com/restserver.php'
+
+class FacebookAuthConsumer(AuthenticationConsumer):
+    
+    def process_authentication_request(self, request):
+        API_KEY = str(settings.FB_API_KEY)
+
+        if API_KEY in request.COOKIES:
+            if self.check_cookies_signature(request.COOKIES):
+                if self.check_session_expiry(request.COOKIES):
+                    return request.COOKIES[API_KEY + '_user']
+                else:
+                    raise InvalidAuthentication(_('Sorry, your Facebook session has expired, please try again'))
+            else:
+                raise InvalidAuthentication(_('The authentication with Facebook connect failed due to an invalid signature'))
+        else:
+            raise InvalidAuthentication(_('The authentication with Facebook connect failed, cannot find authentication tokens'))
+
+    def generate_signature(self, values):
+        keys = []
+
+        for key in sorted(values.keys()):
+            keys.append(key)
+
+        signature = ''.join(['%s=%s' % (key,  values[key]) for key in keys]) + str(settings.FB_APP_SECRET)
+        return hashlib.md5(signature).hexdigest()
+
+    def check_session_expiry(self, cookies):
+        return datetime.fromtimestamp(float(cookies[settings.FB_API_KEY+'_expires'])) > datetime.now()
+
+    def check_cookies_signature(self, cookies):
+        API_KEY = str(settings.FB_API_KEY)
+
+        values = {}
+
+        for key in cookies.keys():
+            if (key.startswith(API_KEY + '_')):
+                values[key.replace(API_KEY + '_',  '')] = cookies[key]
+
+        return self.generate_signature(values) == cookies[API_KEY]
+
+    def get_user_data(self, key):
+        request_data = {
+            'method': 'Users.getInfo',
+            'api_key': settings.FB_API_KEY,
+            'call_id': time(),
+            'v': '1.0',
+            'uids': key,
+            'fields': 'name,first_name,last_name,email',
+            'format': 'json',
+        }
+
+        request_data['sig'] = self.generate_signature(request_data)
+        fb_response = load_json(urlopen(REST_SERVER, urlencode(request_data)))[0]
+
+        return {
+            'username': fb_response['first_name'] + ' ' + fb_response['last_name'],
+            'email': fb_response['email']
+        }
+
+class FacebookAuthContext(ConsumerTemplateContext):
+    mode = 'BIGICON'
+    type = 'CUSTOM'
+    weight = 100
+    human_name = 'Facebook'
+    code_template = 'modules/facebookauth/button.html'
+    extra_css = ["http://www.facebook.com/css/connect/connect_button.css"]
+
+    API_KEY = settings.FB_API_KEY
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/facebookauth/settings.py b/forum/modules/template_loader.py/forum_modules/facebookauth/settings.py
new file mode 100644 (file)
index 0000000..7f34a21
--- /dev/null
@@ -0,0 +1,17 @@
+from forum.settings import EXT_KEYS_SET
+from forum.settings.base import Setting
+
+FB_API_KEY = Setting('FB_API_KEY', '', EXT_KEYS_SET, dict(
+label = "Facebook API key",
+help_text = """
+Get this key at the <a href="http://www.facebook.com/developers/">Facebook developers network</a> to enable
+authentication in your site through facebook.
+""",
+required=False))
+
+FB_APP_SECRET = Setting('FB_APP_SECRET', '', EXT_KEYS_SET, dict(
+label = "Facebook APP secret",
+help_text = """
+This your facebook app secret that you'll get in the same place as the API key.
+""",
+required=False))
diff --git a/forum/modules/template_loader.py/forum_modules/facebookauth/templates/button.html b/forum/modules/template_loader.py/forum_modules/facebookauth/templates/button.html
new file mode 100644 (file)
index 0000000..ceae1fc
--- /dev/null
@@ -0,0 +1,38 @@
+<script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php/en_US" type="text/javascript"></script>\r
+<script type="text/javascript">\r
+    var FB_API_KEY = "{{ provider.API_KEY }}";\r
+    var FB_CHANNEL_PATH = "{% url  xd_receiver %}";\r
+\r
+    FB.init(FB_API_KEY, FB_CHANNEL_PATH, {permsToRequestOnConnect : "email"});\r
+\r
+    function FB_ConnectPostAuthorization() {\r
+        if ($('#validate_email').attr('checked')) {\r
+            FB_RequireFeatures(["Api"], function(){\r
+                var api = FB.Facebook.apiClient;\r
+                var fb_uid = api.get_session().uid;\r
+\r
+                $.post('{% url  facebook_user_is_registered %}', {'fb_uid': fb_uid}, function(response) {\r
+                    if (response != "yes") {\r
+                        api.users_hasAppPermission("email", function(result) {\r
+                            if (!result) {\r
+                                FB.Connect.showPermissionDialog("email", redirect_to_done_page);\r
+                            } else {\r
+                                redirect_to_done_page()\r
+                            }\r
+                        })\r
+                    } else {\r
+                        redirect_to_done_page()\r
+                    }\r
+                });\r
+            });\r
+        } else {\r
+            redirect_to_done_page();\r
+        }\r
+    }\r
+\r
+    function redirect_to_done_page() {\r
+        window.location = "{% url auth_provider_done provider=provider.id %}";\r
+    }\r
+\r
+</script>\r
+<fb:login-button v="2" size="medium" onlogin="FB_ConnectPostAuthorization()">Facebook</fb:login-button>
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/facebookauth/templates/xd_receiver.html b/forum/modules/template_loader.py/forum_modules/facebookauth/templates/xd_receiver.html
new file mode 100644 (file)
index 0000000..9c1664d
--- /dev/null
@@ -0,0 +1 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <body> <script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/XdCommReceiver.js" type="text/javascript"></script> </body> </html>\r
diff --git a/forum/modules/template_loader.py/forum_modules/facebookauth/urls.py b/forum/modules/template_loader.py/forum_modules/facebookauth/urls.py
new file mode 100644 (file)
index 0000000..cbe3b6c
--- /dev/null
@@ -0,0 +1,9 @@
+from django.conf.urls.defaults import *
+from django.views.generic.simple import direct_to_template
+
+from views import user_is_registered
+
+urlpatterns = patterns('',
+    url(r'^xd_receiver.htm$',  direct_to_template,  {'template': 'modules/facebookauth/xd_receiver.html'}, name='xd_receiver'),
+    url(r'^facebook/user_is_registered/', user_is_registered, name="facebook_user_is_registered"),
+)
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/facebookauth/views.py b/forum/modules/template_loader.py/forum_modules/facebookauth/views.py
new file mode 100644 (file)
index 0000000..f77c628
--- /dev/null
@@ -0,0 +1,11 @@
+from forum.models import AuthKeyUserAssociation
+from django.http import HttpResponse
+
+def user_is_registered(request):
+    try:
+        fb_uid = request.POST['fb_uid']
+        #print fb_uid
+        AuthKeyUserAssociation.objects.get(key=fb_uid)
+        return HttpResponse('yes')
+    except:
+        return HttpResponse('no')
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/localauth/__init__.py b/forum/modules/template_loader.py/forum_modules/localauth/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/forum/modules/template_loader.py/forum_modules/localauth/authentication.py b/forum/modules/template_loader.py/forum_modules/localauth/authentication.py
new file mode 100644 (file)
index 0000000..837b756
--- /dev/null
@@ -0,0 +1,19 @@
+from forum.authentication.base import AuthenticationConsumer, ConsumerTemplateContext, InvalidAuthentication
+from forms import ClassicLoginForm
+
+class LocalAuthConsumer(AuthenticationConsumer):
+    def process_authentication_request(self, request):
+        form_auth = ClassicLoginForm(request.POST)
+
+        if form_auth.is_valid():
+            return form_auth.get_user()
+        else:
+            raise InvalidAuthentication(" ".join(form_auth.errors.values()[0]))
+
+class LocalAuthContext(ConsumerTemplateContext):
+    mode = 'STACK_ITEM'                      
+    weight = 1000
+    human_name = 'Local authentication'
+    stack_item_template = 'modules/localauth/loginform.html'
+    show_to_logged_in_user = False
+
diff --git a/forum/modules/template_loader.py/forum_modules/localauth/forms.py b/forum/modules/template_loader.py/forum_modules/localauth/forms.py
new file mode 100644 (file)
index 0000000..9529bba
--- /dev/null
@@ -0,0 +1,98 @@
+from forum.forms import NextUrlField, UserNameField, UserEmailField, SetPasswordForm
+from forum.models import Question
+from forum.modules import call_all_handlers
+from django.contrib.contenttypes.models import ContentType
+from django.utils.translation import ugettext as _
+from django.contrib.auth import authenticate
+from django import forms
+import logging
+
+class ClassicRegisterForm(SetPasswordForm):
+    """ legacy registration form """
+
+    next = NextUrlField()
+    username = UserNameField()
+    email = UserEmailField()
+
+    def __init__(self, *args, **kwargs):
+        super(ClassicRegisterForm, self).__init__(*args, **kwargs)
+
+        spam_fields = call_all_handlers('create_anti_spam_field')
+        if spam_fields:
+            spam_fields = dict(spam_fields)
+            for name, field in spam_fields.items():
+                self.fields[name] = field
+
+            self._anti_spam_fields = spam_fields.keys()
+        else:
+            self._anti_spam_fields = []
+
+    def anti_spam_fields(self):
+        return [self[name] for name in self._anti_spam_fields]
+
+class ClassicLoginForm(forms.Form):
+    """ legacy account signin form """
+    next = NextUrlField()
+    username = UserNameField(required=False, skip_clean=True)
+    password = forms.CharField(max_length=128,
+                               widget=forms.widgets.PasswordInput(attrs={'class':'required login'}),
+                               required=False)
+
+    def __init__(self, data=None, files=None, auto_id='id_%s',
+                 prefix=None, initial=None):
+        super(ClassicLoginForm, self).__init__(data, files, auto_id,
+                                               prefix, initial)
+        self.user_cache = None
+
+    def _clean_nonempty_field(self, field):
+        value = None
+        if field in self.cleaned_data:
+            value = self.cleaned_data[field].strip()
+            if value == '':
+                value = None
+        self.cleaned_data[field] = value
+        return value
+
+    def clean_username(self):
+        return self._clean_nonempty_field('username')
+
+    def clean_password(self):
+        return self._clean_nonempty_field('password')
+
+    def clean(self):
+        error_list = []
+        username = self.cleaned_data['username']
+        password = self.cleaned_data['password']
+
+        self.user_cache = None
+        if username and password:
+            user_ = authenticate(username=username, password=password)
+
+            if user_ is None:
+                del self.cleaned_data['username']
+                del self.cleaned_data['password']
+
+                error_list.insert(0, (_("Please enter valid username and password "
+                "(both are case-sensitive).")))
+
+            if len(error_list) > 0:
+                error_list.insert(0, _('Login failed.'))
+            try:
+                self.user_cache = user_.user
+            except:
+                error_list.append(_('This user is not a valid user'))
+
+        elif password == None and username == None:
+            error_list.append(_('Please enter username and password'))
+        elif password == None:
+            error_list.append(_('Please enter your password'))
+        elif username == None:
+            error_list.append(_('Please enter user name'))
+        if len(error_list) > 0:
+            self._errors['__all__'] = forms.util.ErrorList(error_list)
+
+        return self.cleaned_data
+
+    def get_user(self):
+        """ get authenticated user """
+        return self.user_cache
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/localauth/templates/loginform.html b/forum/modules/template_loader.py/forum_modules/localauth/templates/loginform.html
new file mode 100644 (file)
index 0000000..e66f340
--- /dev/null
@@ -0,0 +1,31 @@
+{% load i18n %}\r
+\r
+<fieldset id='local_login_fs'>\r
+  <p><span class='big strong'>{% trans 'Enter your local user name and password' %}</span><br/><span class='grey'>({% trans 'or select your external provider above' %})</span></p>\r
+  <table>\r
+    <tr>\r
+        <td>\r
+             <label for="id_username">{% trans 'Login name' %}</label>\r
+        </td>\r
+        <td>\r
+             <input id="id_username" type="text" class="required login" name="username" maxlength="30" />\r
+        </td>\r
+    </tr>\r
+    <tr>\r
+        <td>\r
+              <label for="id_password">{% trans 'Password' %}</label>\r
+        </td>\r
+        <td>\r
+             <input id="id_password" type="password" class="required login" name="password" maxlength="128" />\r
+        </td>\r
+    </tr>\r
+    <tr>\r
+        <td>\r
+            <input id="blogin" name="blogin" type="submit" value="{% trans 'Login' %}" />\r
+        </td>\r
+        <td>\r
+              <a href="{% url auth_local_register %}">{% trans 'Create account' %}</a><span>&nbsp;|&nbsp;</span><a href="{% url auth_request_tempsignin %}">{% trans 'Forgot your password?' %}</a>\r
+        </td>\r
+    </tr>\r
+  </table>\r
+</fieldset>\r
diff --git a/forum/modules/template_loader.py/forum_modules/localauth/urls.py b/forum/modules/template_loader.py/forum_modules/localauth/urls.py
new file mode 100644 (file)
index 0000000..aeebc40
--- /dev/null
@@ -0,0 +1,8 @@
+from django.conf.urls.defaults import *
+from django.views.generic.simple import direct_to_template
+from django.utils.translation import ugettext as _
+import views as app
+
+urlpatterns = patterns('',
+    url(r'^%s%s%s$' % (_('account/'), _('local/'),  _('register/')), app.register, name='auth_local_register'),
+)
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/localauth/views.py b/forum/modules/template_loader.py/forum_modules/localauth/views.py
new file mode 100644 (file)
index 0000000..e1daff3
--- /dev/null
@@ -0,0 +1,43 @@
+from forum.models import User
+from django.shortcuts import render_to_response
+from django.template import RequestContext
+from django.utils.translation import ugettext as _
+
+from forms import ClassicRegisterForm
+from forum.forms import SimpleEmailSubscribeForm
+from forum.views.auth import login_and_forward
+from forum.actions import UserJoinsAction
+
+def register(request):
+    if request.method == 'POST':
+        form = ClassicRegisterForm(request.POST)
+        email_feeds_form = SimpleEmailSubscribeForm(request.POST)
+
+        if form.is_valid() and email_feeds_form.is_valid():
+            username = form.cleaned_data['username']
+            password = form.cleaned_data['password1']
+            email = form.cleaned_data['email']
+
+            user_ = User(username=username, email=email)
+            user_.set_password(password)
+
+            if User.objects.all().count() == 0:
+                user_.is_superuser = True
+                user_.is_staff = True
+
+            user_.save()
+            UserJoinsAction(user=user_, ip=request.META['REMOTE_ADDR']).save()
+
+            if email_feeds_form.cleaned_data['subscribe'] == 'n':
+                user_.subscription_settings.enable_notifications = False
+                user_.subscription_settings.save()
+
+            return login_and_forward(request, user_, None, _("A welcome email has been sent to your email address. "))
+    else:
+        form = ClassicRegisterForm(initial={'next':'/'})
+        email_feeds_form = SimpleEmailSubscribeForm()
+
+    return render_to_response('auth/complete.html', {
+        'form1': form,
+        'email_feeds_form': email_feeds_form
+        }, context_instance=RequestContext(request))
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/oauthauth/__init__.py b/forum/modules/template_loader.py/forum_modules/oauthauth/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/forum/modules/template_loader.py/forum_modules/oauthauth/authentication.py b/forum/modules/template_loader.py/forum_modules/oauthauth/authentication.py
new file mode 100644 (file)
index 0000000..93cdc59
--- /dev/null
@@ -0,0 +1,41 @@
+from consumer import OAuthAbstractAuthConsumer
+from forum.authentication.base import ConsumerTemplateContext
+
+try:
+    import json as simplejson
+except ImportError:
+    from django.utils import simplejson
+
+from lib import oauth
+import settings
+
+class TwitterAuthConsumer(OAuthAbstractAuthConsumer):
+    def __init__(self):
+        OAuthAbstractAuthConsumer.__init__(self,
+                str(settings.TWITTER_CONSUMER_KEY),
+                str(settings.TWITTER_CONSUMER_SECRET),
+                "twitter.com",
+                "https://twitter.com/oauth/request_token",
+                "https://twitter.com/oauth/access_token",
+                "https://twitter.com/oauth/authorize",
+        )
+
+    def get_user_data(self, key):
+        json = self.fetch_data(key, "https://twitter.com/account/verify_credentials.json")
+        
+        if 'screen_name' in json:
+            creds = simplejson.loads(json)
+
+            return {
+                'username': creds['screen_name']
+            }
+        
+        
+        return {}
+
+class TwitterAuthContext(ConsumerTemplateContext):
+    mode = 'BIGICON'
+    type = 'DIRECT'
+    weight = 150
+    human_name = 'Twitter'
+    icon = '/media/images/openid/twitter.png'
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/oauthauth/consumer.py b/forum/modules/template_loader.py/forum_modules/oauthauth/consumer.py
new file mode 100644 (file)
index 0000000..7473414
--- /dev/null
@@ -0,0 +1,87 @@
+import urllib
+import urllib2
+import httplib
+import time
+
+from forum.authentication.base import AuthenticationConsumer, InvalidAuthentication
+from django.utils.translation import ugettext as _
+
+from lib import oauth
+
+class OAuthAbstractAuthConsumer(AuthenticationConsumer):
+
+    def __init__(self, consumer_key, consumer_secret, server_url, request_token_url, access_token_url, authorization_url):
+        self.consumer_secret = consumer_secret
+        self.consumer_key = consumer_key
+
+        self.consumer = oauth.OAuthConsumer(consumer_key, consumer_secret)
+        self.signature_method = oauth.OAuthSignatureMethod_HMAC_SHA1()
+
+        self.server_url = server_url
+        self.request_token_url = request_token_url
+        self.access_token_url = access_token_url
+        self.authorization_url = authorization_url
+
+    def prepare_authentication_request(self, request, redirect_to):
+        request_token = self.fetch_request_token()
+        request.session['unauthed_token'] = request_token.to_string()
+        return self.authorize_token_url(request_token)
+
+    def process_authentication_request(self, request):
+        unauthed_token = request.session.get('unauthed_token', None)
+        if not unauthed_token:
+             raise InvalidAuthentication(_('Error, the oauth token is not on the server'))
+
+        token = oauth.OAuthToken.from_string(unauthed_token)
+
+        if token.key != request.GET.get('oauth_token', 'no-token'):
+            raise InvalidAuthentication(_("Something went wrong! Auth tokens do not match"))
+
+        access_token = self.fetch_access_token(token)
+
+        return access_token.to_string()
+
+    def get_user_data(self, key):
+        #token = oauth.OAuthToken.from_string(access_token)
+        return {}
+        
+    def fetch_request_token(self):
+        oauth_request = oauth.OAuthRequest.from_consumer_and_token(self.consumer, http_url=self.request_token_url)
+        oauth_request.sign_request(self.signature_method, self.consumer, None)
+        params = oauth_request.parameters
+        data = urllib.urlencode(params)
+        full_url='%s?%s'%(self.request_token_url, data)
+        response = urllib2.urlopen(full_url)
+        return oauth.OAuthToken.from_string(response.read())
+
+    def authorize_token_url(self, token, callback_url=None):
+        oauth_request = oauth.OAuthRequest.from_token_and_callback(token=token,\
+                        callback=callback_url, http_url=self.authorization_url)
+        params = oauth_request.parameters
+        data = urllib.urlencode(params)
+        full_url='%s?%s'%(self.authorization_url, data)
+        return full_url
+
+    def fetch_access_token(self, token):
+        oauth_request = oauth.OAuthRequest.from_consumer_and_token(self.consumer, token=token, http_url=self.access_token_url)
+        oauth_request.sign_request(self.signature_method, self.consumer, token)
+        params = oauth_request.parameters
+        data = urllib.urlencode(params)
+        full_url='%s?%s'%(self.access_token_url, data)
+        response = urllib2.urlopen(full_url)
+        return oauth.OAuthToken.from_string(response.read())
+
+    def fetch_data(self, token, http_url, parameters=None):
+        access_token = oauth.OAuthToken.from_string(token)
+        oauth_request = oauth.OAuthRequest.from_consumer_and_token(
+            self.consumer, token=access_token, http_method="GET",
+            http_url=http_url, parameters=parameters,
+        )
+        oauth_request.sign_request(self.signature_method, self.consumer, access_token)
+
+        url = oauth_request.to_url()
+        connection = httplib.HTTPSConnection(self.server_url)
+        connection.request(oauth_request.http_method, url)
+
+        return connection.getresponse().read()
+
diff --git a/forum/modules/template_loader.py/forum_modules/oauthauth/lib/__init__.py b/forum/modules/template_loader.py/forum_modules/oauthauth/lib/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/forum/modules/template_loader.py/forum_modules/oauthauth/lib/oauth.py b/forum/modules/template_loader.py/forum_modules/oauthauth/lib/oauth.py
new file mode 100644 (file)
index 0000000..89abf85
--- /dev/null
@@ -0,0 +1,594 @@
+"""
+The MIT License
+
+Copyright (c) 2007 Leah Culver
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+"""
+
+import cgi
+import urllib
+import time
+import random
+import urlparse
+import hmac
+import binascii
+
+
+VERSION = '1.0' # Hi Blaine!
+HTTP_METHOD = 'GET'
+SIGNATURE_METHOD = 'PLAINTEXT'
+
+
+class OAuthError(RuntimeError):
+    """Generic exception class."""
+    def __init__(self, message='OAuth error occured.'):
+        self.message = message
+
+def build_authenticate_header(realm=''):
+    """Optional WWW-Authenticate header (401 error)"""
+    return {'WWW-Authenticate': 'OAuth realm="%s"' % realm}
+
+def escape(s):
+    """Escape a URL including any /."""
+    return urllib.quote(s, safe='~')
+
+def _utf8_str(s):
+    """Convert unicode to utf-8."""
+    if isinstance(s, unicode):
+        return s.encode("utf-8")
+    else:
+        return str(s)
+
+def generate_timestamp():
+    """Get seconds since epoch (UTC)."""
+    return int(time.time())
+
+def generate_nonce(length=8):
+    """Generate pseudorandom number."""
+    return ''.join([str(random.randint(0, 9)) for i in range(length)])
+
+
+class OAuthConsumer(object):
+    """Consumer of OAuth authentication.
+
+    OAuthConsumer is a data type that represents the identity of the Consumer
+    via its shared secret with the Service Provider.
+
+    """
+    key = None
+    secret = None
+
+    def __init__(self, key, secret):
+        self.key = key
+        self.secret = secret
+
+
+class OAuthToken(object):
+    """OAuthToken is a data type that represents an End User via either an access
+    or request token.
+
+    key -- the token
+    secret -- the token secret
+
+    """
+    key = None
+    secret = None
+
+    def __init__(self, key, secret):
+        self.key = key
+        self.secret = secret
+
+    def to_string(self):
+        return urllib.urlencode({'oauth_token': self.key,
+            'oauth_token_secret': self.secret})
+
+    def from_string(s):
+        """ Returns a token from something like:
+        oauth_token_secret=xxx&oauth_token=xxx
+        """
+        params = cgi.parse_qs(s, keep_blank_values=False)
+        key = params['oauth_token'][0]
+        secret = params['oauth_token_secret'][0]
+        return OAuthToken(key, secret)
+    from_string = staticmethod(from_string)
+
+    def __str__(self):
+        return self.to_string()
+
+
+class OAuthRequest(object):
+    """OAuthRequest represents the request and can be serialized.
+
+    OAuth parameters:
+        - oauth_consumer_key
+        - oauth_token
+        - oauth_signature_method
+        - oauth_signature
+        - oauth_timestamp
+        - oauth_nonce
+        - oauth_version
+        ... any additional parameters, as defined by the Service Provider.
+    """
+    parameters = None # OAuth parameters.
+    http_method = HTTP_METHOD
+    http_url = None
+    version = VERSION
+
+    def __init__(self, http_method=HTTP_METHOD, http_url=None, parameters=None):
+        self.http_method = http_method
+        self.http_url = http_url
+        self.parameters = parameters or {}
+
+    def set_parameter(self, parameter, value):
+        self.parameters[parameter] = value
+
+    def get_parameter(self, parameter):
+        try:
+            return self.parameters[parameter]
+        except:
+            raise OAuthError('Parameter not found: %s' % parameter)
+
+    def _get_timestamp_nonce(self):
+        return self.get_parameter('oauth_timestamp'), self.get_parameter(
+            'oauth_nonce')
+
+    def get_nonoauth_parameters(self):
+        """Get any non-OAuth parameters."""
+        parameters = {}
+        for k, v in self.parameters.iteritems():
+            # Ignore oauth parameters.
+            if k.find('oauth_') < 0:
+                parameters[k] = v
+        return parameters
+
+    def to_header(self, realm=''):
+        """Serialize as a header for an HTTPAuth request."""
+        auth_header = 'OAuth realm="%s"' % realm
+        # Add the oauth parameters.
+        if self.parameters:
+            for k, v in self.parameters.iteritems():
+                if k[:6] == 'oauth_':
+                    auth_header += ', %s="%s"' % (k, escape(str(v)))
+        return {'Authorization': auth_header}
+
+    def to_postdata(self):
+        """Serialize as post data for a POST request."""
+        return '&'.join(['%s=%s' % (escape(str(k)), escape(str(v))) \
+            for k, v in self.parameters.iteritems()])
+
+    def to_url(self):
+        """Serialize as a URL for a GET request."""
+        return '%s?%s' % (self.get_normalized_http_url(), self.to_postdata())
+
+    def get_normalized_parameters(self):
+        """Return a string that contains the parameters that must be signed."""
+        params = self.parameters
+        try:
+            # Exclude the signature if it exists.
+            del params['oauth_signature']
+        except:
+            pass
+        # Escape key values before sorting.
+        key_values = [(escape(_utf8_str(k)), escape(_utf8_str(v))) \
+            for k,v in params.items()]
+        # Sort lexicographically, first after key, then after value.
+        key_values.sort()
+        # Combine key value pairs into a string.
+        return '&'.join(['%s=%s' % (k, v) for k, v in key_values])
+
+    def get_normalized_http_method(self):
+        """Uppercases the http method."""
+        return self.http_method.upper()
+
+    def get_normalized_http_url(self):
+        """Parses the URL and rebuilds it to be scheme://host/path."""
+        parts = urlparse.urlparse(self.http_url)
+        scheme, netloc, path = parts[:3]
+        # Exclude default port numbers.
+        if scheme == 'http' and netloc[-3:] == ':80':
+            netloc = netloc[:-3]
+        elif scheme == 'https' and netloc[-4:] == ':443':
+            netloc = netloc[:-4]
+        return '%s://%s%s' % (scheme, netloc, path)
+
+    def sign_request(self, signature_method, consumer, token):
+        """Set the signature parameter to the result of build_signature."""
+        # Set the signature method.
+        self.set_parameter('oauth_signature_method',
+            signature_method.get_name())
+        # Set the signature.
+        self.set_parameter('oauth_signature',
+            self.build_signature(signature_method, consumer, token))
+
+    def build_signature(self, signature_method, consumer, token):
+        """Calls the build signature method within the signature method."""
+        return signature_method.build_signature(self, consumer, token)
+
+    def from_request(http_method, http_url, headers=None, parameters=None,
+            query_string=None):
+        """Combines multiple parameter sources."""
+        if parameters is None:
+            parameters = {}
+
+        # Headers
+        if headers and 'Authorization' in headers:
+            auth_header = headers['Authorization']
+            # Check that the authorization header is OAuth.
+            if auth_header.index('OAuth') > -1:
+                auth_header = auth_header.lstrip('OAuth ')
+                try:
+                    # Get the parameters from the header.
+                    header_params = OAuthRequest._split_header(auth_header)
+                    parameters.update(header_params)
+                except:
+                    raise OAuthError('Unable to parse OAuth parameters from '
+                        'Authorization header.')
+
+        # GET or POST query string.
+        if query_string:
+            query_params = OAuthRequest._split_url_string(query_string)
+            parameters.update(query_params)
+
+        # URL parameters.
+        param_str = urlparse.urlparse(http_url)[4] # query
+        url_params = OAuthRequest._split_url_string(param_str)
+        parameters.update(url_params)
+
+        if parameters:
+            return OAuthRequest(http_method, http_url, parameters)
+
+        return None
+    from_request = staticmethod(from_request)
+
+    def from_consumer_and_token(oauth_consumer, token=None,
+            http_method=HTTP_METHOD, http_url=None, parameters=None):
+        if not parameters:
+            parameters = {}
+
+        defaults = {
+            'oauth_consumer_key': oauth_consumer.key,
+            'oauth_timestamp': generate_timestamp(),
+            'oauth_nonce': generate_nonce(),
+            'oauth_version': OAuthRequest.version,
+        }
+
+        defaults.update(parameters)
+        parameters = defaults
+
+        if token:
+            parameters['oauth_token'] = token.key
+
+        return OAuthRequest(http_method, http_url, parameters)
+    from_consumer_and_token = staticmethod(from_consumer_and_token)
+
+    def from_token_and_callback(token, callback=None, http_method=HTTP_METHOD,
+            http_url=None, parameters=None):
+        if not parameters:
+            parameters = {}
+
+        parameters['oauth_token'] = token.key
+
+        if callback:
+            parameters['oauth_callback'] = callback
+
+        return OAuthRequest(http_method, http_url, parameters)
+    from_token_and_callback = staticmethod(from_token_and_callback)
+
+    def _split_header(header):
+        """Turn Authorization: header into parameters."""
+        params = {}
+        parts = header.split(',')
+        for param in parts:
+            # Ignore realm parameter.
+            if param.find('realm') > -1:
+                continue
+            # Remove whitespace.
+            param = param.strip()
+            # Split key-value.
+            param_parts = param.split('=', 1)
+            # Remove quotes and unescape the value.
+            params[param_parts[0]] = urllib.unquote(param_parts[1].strip('\"'))
+        return params
+    _split_header = staticmethod(_split_header)
+
+    def _split_url_string(param_str):
+        """Turn URL string into parameters."""
+        parameters = cgi.parse_qs(param_str, keep_blank_values=False)
+        for k, v in parameters.iteritems():
+            parameters[k] = urllib.unquote(v[0])
+        return parameters
+    _split_url_string = staticmethod(_split_url_string)
+
+class OAuthServer(object):
+    """A worker to check the validity of a request against a data store."""
+    timestamp_threshold = 300 # In seconds, five minutes.
+    version = VERSION
+    signature_methods = None
+    data_store = None
+
+    def __init__(self, data_store=None, signature_methods=None):
+        self.data_store = data_store
+        self.signature_methods = signature_methods or {}
+
+    def set_data_store(self, data_store):
+        self.data_store = data_store
+
+    def get_data_store(self):
+        return self.data_store
+
+    def add_signature_method(self, signature_method):
+        self.signature_methods[signature_method.get_name()] = signature_method
+        return self.signature_methods
+
+    def fetch_request_token(self, oauth_request):
+        """Processes a request_token request and returns the
+        request token on success.
+        """
+        try:
+            # Get the request token for authorization.
+            token = self._get_token(oauth_request, 'request')
+        except OAuthError:
+            # No token required for the initial token request.
+            version = self._get_version(oauth_request)
+            consumer = self._get_consumer(oauth_request)
+            self._check_signature(oauth_request, consumer, None)
+            # Fetch a new token.
+            token = self.data_store.fetch_request_token(consumer)
+        return token
+
+    def fetch_access_token(self, oauth_request):
+        """Processes an access_token request and returns the
+        access token on success.
+        """
+        version = self._get_version(oauth_request)
+        consumer = self._get_consumer(oauth_request)
+        # Get the request token.
+        token = self._get_token(oauth_request, 'request')
+        self._check_signature(oauth_request, consumer, token)
+        new_token = self.data_store.fetch_access_token(consumer, token)
+        return new_token
+
+    def verify_request(self, oauth_request):
+        """Verifies an api call and checks all the parameters."""
+        # -> consumer and token
+        version = self._get_version(oauth_request)
+        consumer = self._get_consumer(oauth_request)
+        # Get the access token.
+        token = self._get_token(oauth_request, 'access')
+        self._check_signature(oauth_request, consumer, token)
+        parameters = oauth_request.get_nonoauth_parameters()
+        return consumer, token, parameters
+
+    def authorize_token(self, token, user):
+        """Authorize a request token."""
+        return self.data_store.authorize_request_token(token, user)
+
+    def get_callback(self, oauth_request):
+        """Get the callback URL."""
+        return oauth_request.get_parameter('oauth_callback')
+
+    def build_authenticate_header(self, realm=''):
+        """Optional support for the authenticate header."""
+        return {'WWW-Authenticate': 'OAuth realm="%s"' % realm}
+
+    def _get_version(self, oauth_request):
+        """Verify the correct version request for this server."""
+        try:
+            version = oauth_request.get_parameter('oauth_version')
+        except:
+            version = VERSION
+        if version and version != self.version:
+            raise OAuthError('OAuth version %s not supported.' % str(version))
+        return version
+
+    def _get_signature_method(self, oauth_request):
+        """Figure out the signature with some defaults."""
+        try:
+            signature_method = oauth_request.get_parameter(
+                'oauth_signature_method')
+        except:
+            signature_method = SIGNATURE_METHOD
+        try:
+            # Get the signature method object.
+            signature_method = self.signature_methods[signature_method]
+        except:
+            signature_method_names = ', '.join(self.signature_methods.keys())
+            raise OAuthError('Signature method %s not supported try one of the '
+                'following: %s' % (signature_method, signature_method_names))
+
+        return signature_method
+
+    def _get_consumer(self, oauth_request):
+        consumer_key = oauth_request.get_parameter('oauth_consumer_key')
+        consumer = self.data_store.lookup_consumer(consumer_key)
+        if not consumer:
+            raise OAuthError('Invalid consumer.')
+        return consumer
+
+    def _get_token(self, oauth_request, token_type='access'):
+        """Try to find the token for the provided request token key."""
+        token_field = oauth_request.get_parameter('oauth_token')
+        token = self.data_store.lookup_token(token_type, token_field)
+        if not token:
+            raise OAuthError('Invalid %s token: %s' % (token_type, token_field))
+        return token
+
+    def _check_signature(self, oauth_request, consumer, token):
+        timestamp, nonce = oauth_request._get_timestamp_nonce()
+        self._check_timestamp(timestamp)
+        self._check_nonce(consumer, token, nonce)
+        signature_method = self._get_signature_method(oauth_request)
+        try:
+            signature = oauth_request.get_parameter('oauth_signature')
+        except:
+            raise OAuthError('Missing signature.')
+        # Validate the signature.
+        valid_sig = signature_method.check_signature(oauth_request, consumer,
+            token, signature)
+        if not valid_sig:
+            key, base = signature_method.build_signature_base_string(
+                oauth_request, consumer, token)
+            raise OAuthError('Invalid signature. Expected signature base '
+                'string: %s' % base)
+        built = signature_method.build_signature(oauth_request, consumer, token)
+
+    def _check_timestamp(self, timestamp):
+        """Verify that timestamp is recentish."""
+        timestamp = int(timestamp)
+        now = int(time.time())
+        lapsed = now - timestamp
+        if lapsed > self.timestamp_threshold:
+            raise OAuthError('Expired timestamp: given %d and now %s has a '
+                'greater difference than threshold %d' %
+                (timestamp, now, self.timestamp_threshold))
+
+    def _check_nonce(self, consumer, token, nonce):
+        """Verify that the nonce is uniqueish."""
+        nonce = self.data_store.lookup_nonce(consumer, token, nonce)
+        if nonce:
+            raise OAuthError('Nonce already used: %s' % str(nonce))
+
+
+class OAuthClient(object):
+    """OAuthClient is a worker to attempt to execute a request."""
+    consumer = None
+    token = None
+
+    def __init__(self, oauth_consumer, oauth_token):
+        self.consumer = oauth_consumer
+        self.token = oauth_token
+
+    def get_consumer(self):
+        return self.consumer
+
+    def get_token(self):
+        return self.token
+
+    def fetch_request_token(self, oauth_request):
+        """-> OAuthToken."""
+        raise NotImplementedError
+
+    def fetch_access_token(self, oauth_request):
+        """-> OAuthToken."""
+        raise NotImplementedError
+
+    def access_resource(self, oauth_request):
+        """-> Some protected resource."""
+        raise NotImplementedError
+
+
+class OAuthDataStore(object):
+    """A database abstraction used to lookup consumers and tokens."""
+
+    def lookup_consumer(self, key):
+        """-> OAuthConsumer."""
+        raise NotImplementedError
+
+    def lookup_token(self, oauth_consumer, token_type, token_token):
+        """-> OAuthToken."""
+        raise NotImplementedError
+
+    def lookup_nonce(self, oauth_consumer, oauth_token, nonce):
+        """-> OAuthToken."""
+        raise NotImplementedError
+
+    def fetch_request_token(self, oauth_consumer):
+        """-> OAuthToken."""
+        raise NotImplementedError
+
+    def fetch_access_token(self, oauth_consumer, oauth_token):
+        """-> OAuthToken."""
+        raise NotImplementedError
+
+    def authorize_request_token(self, oauth_token, user):
+        """-> OAuthToken."""
+        raise NotImplementedError
+
+
+class OAuthSignatureMethod(object):
+    """A strategy class that implements a signature method."""
+    def get_name(self):
+        """-> str."""
+        raise NotImplementedError
+
+    def build_signature_base_string(self, oauth_request, oauth_consumer, oauth_token):
+        """-> str key, str raw."""
+        raise NotImplementedError
+
+    def build_signature(self, oauth_request, oauth_consumer, oauth_token):
+        """-> str."""
+        raise NotImplementedError
+
+    def check_signature(self, oauth_request, consumer, token, signature):
+        built = self.build_signature(oauth_request, consumer, token)
+        return built == signature
+
+
+class OAuthSignatureMethod_HMAC_SHA1(OAuthSignatureMethod):
+
+    def get_name(self):
+        return 'HMAC-SHA1'
+
+    def build_signature_base_string(self, oauth_request, consumer, token):
+        sig = (
+            escape(oauth_request.get_normalized_http_method()),
+            escape(oauth_request.get_normalized_http_url()),
+            escape(oauth_request.get_normalized_parameters()),
+        )
+
+        key = '%s&' % escape(consumer.secret)
+        if token:
+            key += escape(token.secret)
+        raw = '&'.join(sig)
+        return key, raw
+
+    def build_signature(self, oauth_request, consumer, token):
+        """Builds the base signature string."""
+        key, raw = self.build_signature_base_string(oauth_request, consumer,
+            token)
+
+        # HMAC object.
+        try:
+            import hashlib # 2.5
+            hashed = hmac.new(key, raw, hashlib.sha1)
+        except:
+            import sha # Deprecated
+            hashed = hmac.new(key, raw, sha)
+
+        # Calculate the digest base 64.
+        return binascii.b2a_base64(hashed.digest())[:-1]
+
+
+class OAuthSignatureMethod_PLAINTEXT(OAuthSignatureMethod):
+
+    def get_name(self):
+        return 'PLAINTEXT'
+
+    def build_signature_base_string(self, oauth_request, consumer, token):
+        """Concatenates the consumer key and secret."""
+        sig = '%s&' % escape(consumer.secret)
+        if token:
+            sig = sig + escape(token.secret)
+        return sig, sig
+
+    def build_signature(self, oauth_request, consumer, token):
+        key, raw = self.build_signature_base_string(oauth_request, consumer,
+            token)
+        return key
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/oauthauth/settings.py b/forum/modules/template_loader.py/forum_modules/oauthauth/settings.py
new file mode 100644 (file)
index 0000000..7e9ef8c
--- /dev/null
@@ -0,0 +1,19 @@
+from forum.settings import EXT_KEYS_SET
+from forum.settings.base import Setting
+
+TWITTER_CONSUMER_KEY = Setting('TWITTER_CONSUMER_KEY', '', EXT_KEYS_SET, dict(
+label = "Twitter consumer key",
+help_text = """
+Get this key at the <a href="http://twitter.com/apps/">Twitter apps</a> to enable
+authentication in your site through Twitter.
+""",
+required=False))
+
+TWITTER_CONSUMER_SECRET = Setting('TWITTER_CONSUMER_SECRET', '', EXT_KEYS_SET, dict(
+label = "Twitter consumer secret",
+help_text = """
+This your Twitter consumer secret that you'll get in the same place as the consumer key.
+""",
+required=False))
+
+
diff --git a/forum/modules/template_loader.py/forum_modules/openidauth/__init__.py b/forum/modules/template_loader.py/forum_modules/openidauth/__init__.py
new file mode 100644 (file)
index 0000000..358a57d
--- /dev/null
@@ -0,0 +1,5 @@
+try:
+    import openid
+    CAN_USE = True
+except:
+    CAN_USE = False
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/openidauth/authentication.py b/forum/modules/template_loader.py/forum_modules/openidauth/authentication.py
new file mode 100644 (file)
index 0000000..0afd4c6
--- /dev/null
@@ -0,0 +1,188 @@
+from consumer import OpenIdAbstractAuthConsumer
+from forum.authentication.base import ConsumerTemplateContext
+
+class GoogleAuthConsumer(OpenIdAbstractAuthConsumer):
+    def get_user_url(self, request):
+        return 'https://www.google.com/accounts/o8/id'
+
+class GoogleAuthContext(ConsumerTemplateContext):
+    mode = 'BIGICON'
+    type = 'DIRECT'
+    weight = 200
+    human_name = 'Google'
+    icon = '/media/images/openid/google.gif'
+
+
+
+class YahooAuthConsumer(OpenIdAbstractAuthConsumer):
+    def get_user_url(self, request):
+        return 'http://yahoo.com/'
+
+class YahooAuthContext(ConsumerTemplateContext):
+    mode = 'BIGICON'
+    type = 'DIRECT'
+    weight = 300
+    human_name = 'Yahoo'
+    icon = '/media/images/openid/yahoo.gif'
+
+
+
+class AolAuthConsumer(OpenIdAbstractAuthConsumer):
+    def get_user_url(self, request):
+        uname = request.POST['input_field']
+        return 'http://openid.aol.com/' + uname
+
+class AolAuthContext(ConsumerTemplateContext):
+    mode = 'SMALLICON'
+    type = 'SIMPLE_FORM'
+    simple_form_context = {
+        'your_what': 'AOL screen name'
+    }
+    weight = 200
+    human_name = 'AOL'
+    icon = '/media/images/openid/aol.png'
+
+
+class MyOpenIdAuthConsumer(OpenIdAbstractAuthConsumer):
+    dataype2ax_schema = {
+        #'username': ('http://schema.openid.net/namePerson/friendly', 'friendly'),
+        'email': 'http://schema.openid.net/contact/email',
+        #'web': 'http://schema.openid.net/contact/web/default',
+        #'birthdate': ('http://schema.openid.net/birthDate', 'birthDate'),
+    }
+
+    def get_user_url(self, request):
+        blog_name = request.POST['input_field']
+        return "http://%s.myopenid.com/" % blog_name
+
+class MyOpenIdAuthContext(ConsumerTemplateContext):
+    mode = 'BIGICON'
+    type = 'SIMPLE_FORM'
+    simple_form_context = {
+        'your_what': 'MyOpenID user name'
+    }
+    weight = 400
+    human_name = 'MyOpenID'
+    icon = '/media/images/openid/myopenid_big.png'
+
+
+class FlickrAuthConsumer(OpenIdAbstractAuthConsumer):
+    def get_user_url(self, request):
+        blog_name = request.POST['input_field']
+        return "http://flickr.com/%s/" % blog_name
+
+class FlickrAuthContext(ConsumerTemplateContext):
+    mode = 'SMALLICON'
+    type = 'SIMPLE_FORM'
+    simple_form_context = {
+        'your_what': 'Flickr user name'
+    }
+    weight = 250
+    human_name = 'Flickr'
+    icon = '/media/images/openid/flickr.png'
+
+
+class TechnoratiAuthConsumer(OpenIdAbstractAuthConsumer):
+    def get_user_url(self, request):
+        blog_name = request.POST['input_field']
+        return "http://technorati.com/people/technorati/%s/" % blog_name
+
+class TechnoratiAuthContext(ConsumerTemplateContext):
+    mode = 'SMALLICON'
+    type = 'SIMPLE_FORM'
+    simple_form_context = {
+        'your_what': 'Technorati user name'
+    }
+    weight = 260
+    human_name = 'Technorati'
+    icon = '/media/images/openid/technorati.png'
+
+
+class WordpressAuthConsumer(OpenIdAbstractAuthConsumer):
+    def get_user_url(self, request):
+        blog_name = request.POST['input_field']
+        return "http://%s.wordpress.com/" % blog_name
+
+class WordpressAuthContext(ConsumerTemplateContext):
+    mode = 'SMALLICON'
+    type = 'SIMPLE_FORM'
+    simple_form_context = {
+        'your_what': 'Wordpress blog name'
+    }
+    weight = 270
+    human_name = 'Wordpress'
+    icon = '/media/images/openid/wordpress.png'
+
+
+class BloggerAuthConsumer(OpenIdAbstractAuthConsumer):
+    def get_user_url(self, request):
+        blog_name = request.POST['input_field']
+        return "http://%s.blogspot.com/" % blog_name
+
+class BloggerAuthContext(ConsumerTemplateContext):
+    mode = 'SMALLICON'
+    type = 'SIMPLE_FORM'
+    simple_form_context = {
+        'your_what': 'Blogger blog name'
+    }
+    weight = 300
+    human_name = 'Blogger'
+    icon = '/media/images/openid/blogger.png'
+
+
+class LiveJournalAuthConsumer(OpenIdAbstractAuthConsumer):
+    def get_user_url(self, request):
+        blog_name = request.POST['input_field']
+        return "http://%s.livejournal.com/" % blog_name
+
+class LiveJournalAuthContext(ConsumerTemplateContext):
+    mode = 'SMALLICON'
+    type = 'SIMPLE_FORM'
+    simple_form_context = {
+        'your_what': 'LiveJournal blog name'
+    }
+    weight = 310
+    human_name = 'LiveJournal'
+    icon = '/media/images/openid/livejournal.png'
+
+
+class ClaimIdAuthConsumer(OpenIdAbstractAuthConsumer):
+    def get_user_url(self, request):
+        blog_name = request.POST['input_field']
+        return "http://claimid.com/%s" % blog_name
+
+class ClaimIdAuthContext(ConsumerTemplateContext):
+    mode = 'SMALLICON'
+    type = 'SIMPLE_FORM'
+    simple_form_context = {
+        'your_what': 'ClaimID user name'
+    }
+    weight = 320
+    human_name = 'ClaimID'
+    icon = '/media/images/openid/claimid.png'
+
+class VerisignAuthConsumer(OpenIdAbstractAuthConsumer):
+    def get_user_url(self, request):
+        blog_name = request.POST['input_field']
+        return "http://%s.pip.verisignlabs.com/" % blog_name
+
+class VerisignAuthContext(ConsumerTemplateContext):
+    mode = 'SMALLICON'
+    type = 'SIMPLE_FORM'
+    simple_form_context = {
+        'your_what': 'Verisign user name'
+    }
+    weight = 340
+    human_name = 'Verisign'
+    icon = '/media/images/openid/verisign.png'
+
+    
+class OpenIdUrlAuthConsumer(OpenIdAbstractAuthConsumer):
+    pass
+
+class OpenIdUrlAuthContext(ConsumerTemplateContext):
+    mode = 'STACK_ITEM'
+    weight = 300
+    human_name = 'OpenId url'
+    stack_item_template = 'modules/openidauth/openidurl.html'
+    icon = '/media/images/openid/openid-inputicon.gif'
diff --git a/forum/modules/template_loader.py/forum_modules/openidauth/consumer.py b/forum/modules/template_loader.py/forum_modules/openidauth/consumer.py
new file mode 100644 (file)
index 0000000..cc1e97d
--- /dev/null
@@ -0,0 +1,145 @@
+import re
+
+from django.utils.html import escape
+from django.http import get_host
+
+from forum.authentication.base import AuthenticationConsumer, InvalidAuthentication
+import settings
+
+from openid.yadis import xri
+from openid.consumer.consumer import Consumer, SUCCESS, CANCEL, FAILURE, SETUP_NEEDED
+from openid.consumer.discover import DiscoveryFailure
+from openid.extensions.sreg import SRegRequest, SRegResponse
+from openid.extensions.ax import FetchRequest as AXFetchRequest, AttrInfo, FetchResponse as AXFetchResponse
+from django.utils.translation import ugettext as _
+
+from store import OsqaOpenIDStore
+
+class OpenIdAbstractAuthConsumer(AuthenticationConsumer):
+
+    dataype2ax_schema = {
+        #'username': 'http://axschema.org/namePerson/friendly',
+        'email': 'http://axschema.org/contact/email',
+        #'web': 'http://axschema.org/contact/web/default',
+        #'firstname': 'http://axschema.org/namePerson/first',
+        #'lastname': 'http://axschema.org/namePerson/last',
+        #'birthdate': 'http://axschema.org/birthDate',
+    }
+
+    def get_user_url(self, request):
+        try:
+            return request.POST['openid_identifier']
+        except:
+            raise NotImplementedError()
+
+    def prepare_authentication_request(self, request, redirect_to):
+        if not redirect_to.startswith('http://') or redirect_to.startswith('https://'):
+                   redirect_to =  get_url_host(request) + redirect_to
+
+        user_url = self.get_user_url(request)
+
+        if xri.identifierScheme(user_url) == 'XRI' and getattr(
+            settings, 'OPENID_DISALLOW_INAMES', False
+        ):
+            raise InvalidAuthentication('i-names are not supported')
+
+        consumer = Consumer(request.session, OsqaOpenIDStore())
+
+        try:
+            auth_request = consumer.begin(user_url)
+        except DiscoveryFailure:
+            raise InvalidAuthentication(_('Sorry, but your input is not a valid OpenId'))
+
+        #sreg = getattr(settings, 'OPENID_SREG', False)
+
+        #if sreg:
+        #    s = SRegRequest()
+        #    for sarg in sreg:
+        #        if sarg.lower().lstrip() == "policy_url":
+        #            s.policy_url = sreg[sarg]
+        #        else:
+        #            for v in sreg[sarg].split(','):
+        #                s.requestField(field_name=v.lower().lstrip(), required=(sarg.lower().lstrip() == "required"))
+        #    auth_request.addExtension(s)
+
+        #auth_request.addExtension(SRegRequest(required=['email']))
+
+        if request.session.get('force_email_request', True):
+            axr = AXFetchRequest()
+            for data_type, schema in self.dataype2ax_schema.items():
+                if isinstance(schema, tuple):
+                    axr.add(AttrInfo(schema[0], 1, True, schema[1]))
+                else:
+                    axr.add(AttrInfo(schema, 1, True, data_type))
+
+            auth_request.addExtension(axr)
+
+        trust_root = getattr(
+            settings, 'OPENID_TRUST_ROOT', get_url_host(request) + '/'
+        )
+
+        return auth_request.redirectURL(trust_root, redirect_to)
+
+    def process_authentication_request(self, request):
+        consumer = Consumer(request.session, OsqaOpenIDStore())
+
+        query_dict = dict([
+            (k.encode('utf8'), v.encode('utf8')) for k, v in request.GET.items()
+        ])
+
+        #for i in query_dict.items():
+            #print "%s : %s" % i
+
+        url = get_url_host(request) + request.path
+        openid_response = consumer.complete(query_dict, url)
+
+        if openid_response.status == SUCCESS:
+            if request.session.get('force_email_request', True):
+                try:
+                    ax = AXFetchResponse.fromSuccessResponse(openid_response)
+
+                    axargs = ax.getExtensionArgs()
+
+                    ax_schema2data_type = dict([(s, t) for t, s in self.dataype2ax_schema.items()])
+
+                    available_types = dict([
+                        (ax_schema2data_type[s], re.sub('^type\.', '', n))
+                        for n, s in axargs.items() if s in ax_schema2data_type
+                    ])
+
+                    available_data = dict([
+                        (t, axargs["value.%s.1" % s]) for t, s in available_types.items()
+                    ])
+                    
+                    request.session['auth_consumer_data'] = {
+                        'email': available_data.get('email', None),
+                    }
+
+                except Exception, e:
+                    pass
+                    #import sys, traceback
+                    #traceback.print_exc(file=sys.stdout)
+
+            return request.GET['openid.identity']
+        elif openid_response.status == CANCEL:
+            raise InvalidAuthentication(_('The OpenId authentication request was canceled'))
+        elif openid_response.status == FAILURE:
+            raise InvalidAuthentication(_('The OpenId authentication failed: ') + openid_response.message)
+        elif openid_response.status == SETUP_NEEDED:
+            raise InvalidAuthentication(_('Setup needed'))
+        else:
+            raise InvalidAuthentication(_('The OpenId authentication failed with an unknown status: ') + openid_response.status)
+
+    def get_user_data(self, key):
+        return {}
+
+def get_url_host(request):
+    if request.is_secure():
+        protocol = 'https'
+    else:
+        protocol = 'http'
+    host = escape(get_host(request))
+    return '%s://%s' % (protocol, host)
+
+def get_full_url(request):
+    return get_url_host(request) + request.get_full_path()
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/openidauth/models.py b/forum/modules/template_loader.py/forum_modules/openidauth/models.py
new file mode 100644 (file)
index 0000000..d76902d
--- /dev/null
@@ -0,0 +1,26 @@
+from django.db import models
+
+class OpenIdNonce(models.Model):
+    server_url = models.URLField()
+    timestamp  = models.IntegerField()
+    salt       = models.CharField( max_length=50 )
+
+    def __unicode__(self):
+        return "Nonce: %s" % self.nonce
+
+    class Meta:
+        app_label = 'forum'
+
+class OpenIdAssociation(models.Model):
+    server_url = models.TextField(max_length=2047)
+    handle = models.CharField(max_length=255)
+    secret = models.TextField(max_length=255) # Stored base64 encoded
+    issued = models.IntegerField()
+    lifetime = models.IntegerField()
+    assoc_type = models.TextField(max_length=64)
+
+    def __unicode__(self):
+        return "Association: %s, %s" % (self.server_url, self.handle)
+
+    class Meta:
+        app_label = 'forum'
diff --git a/forum/modules/template_loader.py/forum_modules/openidauth/settings.py b/forum/modules/template_loader.py/forum_modules/openidauth/settings.py
new file mode 100644 (file)
index 0000000..f7c641a
--- /dev/null
@@ -0,0 +1,9 @@
+OPENID_SREG = {
+    "required": "nickname, email",
+    "optional": "postcode, country",
+    "policy_url": ""
+}
+OPENID_AX = [
+            {"type_uri": "http://axschema.org/contact/email", "count": 1, "required": True, "alias": "email"},
+            {"type_uri": "fullname", "count":1 , "required": False, "alias": "fullname"}
+        ]
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/openidauth/store.py b/forum/modules/template_loader.py/forum_modules/openidauth/store.py
new file mode 100644 (file)
index 0000000..8656752
--- /dev/null
@@ -0,0 +1,86 @@
+import time, base64
+
+#thanks to alexlavr
+#see: http://meta.osqa.net/question/25/installation-issue-importerror-cannot-import-name-auth_providers#43
+try:
+    from hashlib import md5 as md
+except ImportError:
+    from md5 import new as md
+
+from openid.store import nonce as oid_nonce
+from openid.store.interface import OpenIDStore
+from openid.association import Association as OIDAssociation
+from django.conf import settings
+
+from models import OpenIdNonce as Nonce, OpenIdAssociation as Association
+
+class OsqaOpenIDStore(OpenIDStore):
+    def __init__(self):
+        self.max_nonce_age = 6 * 60 * 60 # Six hours
+
+    def storeAssociation(self, server_url, association):
+        assoc = Association(
+            server_url = server_url,
+            handle = association.handle,
+            secret = base64.encodestring(association.secret),
+            issued = association.issued,
+            lifetime = association.issued,
+            assoc_type = association.assoc_type
+        )
+        assoc.save()
+
+    def getAssociation(self, server_url, handle=None):
+        assocs = []
+        if handle is not None:
+            assocs = Association.objects.filter(
+                server_url = server_url, handle = handle
+            )
+        else:
+            assocs = Association.objects.filter(
+                server_url = server_url
+            )
+        if not assocs:
+            return None
+        associations = []
+        for assoc in assocs:
+            association = OIDAssociation(
+                assoc.handle, base64.decodestring(assoc.secret), assoc.issued,
+                assoc.lifetime, assoc.assoc_type
+            )
+            if association.getExpiresIn() == 0:
+                self.removeAssociation(server_url, assoc.handle)
+            else:
+                associations.append((association.issued, association))
+        if not associations:
+            return None
+        return associations[-1][1]
+
+    def removeAssociation(self, server_url, handle):
+        assocs = list(Association.objects.filter(
+            server_url = server_url, handle = handle
+        ))
+        assocs_exist = len(assocs) > 0
+        for assoc in assocs:
+            assoc.delete()
+        return assocs_exist
+
+    def storeNonce(self, nonce):
+        nonce, created = Nonce.objects.get_or_create(
+            nonce = nonce, defaults={'expires': int(time.time())}
+        )
+
+    def useNonce(self, server_url, timestamp, salt):
+        if abs(timestamp - time.time()) > oid_nonce.SKEW:
+            return False
+
+        try:
+            nonce = Nonce( server_url=server_url, timestamp=timestamp, salt=salt)
+            nonce.save()
+        except:
+            raise
+        else:
+            return 1
+
+    def getAuthKey(self):
+        # Use first AUTH_KEY_LEN characters of md5 hash of SECRET_KEY
+        return md(settings.SECRET_KEY).hexdigest()[:self.AUTH_KEY_LEN]
diff --git a/forum/modules/template_loader.py/forum_modules/openidauth/templates/openidurl.html b/forum/modules/template_loader.py/forum_modules/openidauth/templates/openidurl.html
new file mode 100644 (file)
index 0000000..8659f5a
--- /dev/null
@@ -0,0 +1,20 @@
+{% load i18n %}\r
+{% load extra_tags %}\r
+\r
+<fieldset>\r
+    <table>\r
+    <tr>\r
+        <td><p id="provider_name_slot">{% trans 'Enter your OpenId Url' %}</p></td>\r
+    </tr>\r
+    <tr>\r
+        <td>\r
+            <input id="openid_identifier" class="icon_input" name="openid_identifier" type="text"\r
+            style="width: 500px; background: url('{% media provider.icon %}') no-repeat left center" />\r
+        </td>\r
+        <td>\r
+            <input type="submit" name="ssignin" value="{% trans 'Login' %}" />\r
+        </td>\r
+    </tr>\r
+    </table>\r
+</fieldset>\r
+\r
diff --git a/forum/modules/template_loader.py/forum_modules/pgfulltext/__init__.py b/forum/modules/template_loader.py/forum_modules/pgfulltext/__init__.py
new file mode 100644 (file)
index 0000000..20cd355
--- /dev/null
@@ -0,0 +1,10 @@
+NAME = 'Postgresql Full Text Search'
+DESCRIPTION = "Enables PostgreSql full text search functionality."
+
+try:
+    import psycopg2
+    from django.conf import settings
+    CAN_USE = settings.DATABASE_ENGINE in ('postgresql_psycopg2', 'postgresql', )
+except:
+    CAN_USE = False
+    
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/pgfulltext/handlers.py b/forum/modules/template_loader.py/forum_modules/pgfulltext/handlers.py
new file mode 100644 (file)
index 0000000..780bfa9
--- /dev/null
@@ -0,0 +1,38 @@
+import re
+from django.db import connection, transaction
+from django.db.models import Q
+from forum.models.question import Question, QuestionManager
+from forum.models.node import Node
+from forum.modules import decorate
+
+word_re = re.compile(r'\w+', re.UNICODE)
+
+@decorate(QuestionManager.search, needs_origin=False)
+def question_search(self, keywords):
+    tsquery = " | ".join(word_re.findall(keywords))
+    ilike = keywords + u"%%"
+
+    return True, self.extra(
+            tables = ['forum_rootnode_doc'],
+            select={
+            'ranking': """
+                                rank_exact_matches(ts_rank_cd('{0.1, 0.2, 0.8, 1.0}'::float4[], "forum_rootnode_doc"."document", to_tsquery('english', %s), 32))
+                                """,
+            },
+            where=["""
+                           "forum_rootnode_doc"."node_id" = "forum_node"."id" AND ("forum_rootnode_doc"."document" @@ to_tsquery('english', %s) OR
+                           "forum_node"."title" ILIKE %s)
+                           """],
+            params=[tsquery, ilike],
+            select_params=[tsquery],
+            )
+
+
+@decorate(Node.delete)
+def delete(origin, self, *args, **kwargs):
+    cursor = connection.cursor()
+    cursor.execute("DELETE FROM forum_rootnode_doc WHERE node_id = %s" % (self.id))
+    transaction.commit_unless_managed()
+    return origin(self, *args, **kwargs)
+
+
diff --git a/forum/modules/template_loader.py/forum_modules/pgfulltext/pg_fts_install.sql b/forum/modules/template_loader.py/forum_modules/pgfulltext/pg_fts_install.sql
new file mode 100644 (file)
index 0000000..c046870
--- /dev/null
@@ -0,0 +1,129 @@
+CREATE OR REPLACE FUNCTION public.create_plpgsql_language ()
+    RETURNS TEXT
+    AS $$
+        CREATE LANGUAGE plpgsql;
+        SELECT 'language plpgsql created'::TEXT;
+    $$
+LANGUAGE 'sql';
+
+SELECT CASE WHEN
+      (SELECT true::BOOLEAN
+         FROM pg_language
+        WHERE lanname='plpgsql')
+    THEN
+      (SELECT 'language already installed'::TEXT)
+    ELSE
+      (SELECT public.create_plpgsql_language())
+    END;
+
+DROP FUNCTION public.create_plpgsql_language ();
+
+CREATE OR REPLACE FUNCTION public.drop_tsv_noderevision_column () RETURNS VOID AS $$
+begin
+        ALTER TABLE forum_noderevision DROP COLUMN tsv;
+        DROP TRIGGER IF EXISTS tsvectorupdate ON forum_noderevision;
+end
+$$ LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION public.tsv_noderevision_column_exists() RETURNS int AS $$
+ SELECT COUNT(attname)::int FROM pg_attribute WHERE attrelid = (SELECT oid FROM pg_class WHERE relname = 'forum_noderevision') AND attname = 'tsv';
+$$ LANGUAGE 'sql';
+
+select case when public.tsv_noderevision_column_exists()>0 then public.drop_tsv_noderevision_column()end;
+
+drop function drop_tsv_noderevision_column();
+drop function tsv_noderevision_column_exists();
+
+CREATE OR REPLACE FUNCTION set_doctable_tsv() RETURNS TRIGGER AS $$
+declare
+  root_id int;
+  doc tsvector;
+  rcount int;
+  cv tsvector;
+begin
+    SELECT abs_parent_id INTO root_id FROM forum_node WHERE id = new.node_id;
+
+    IF root_id IS NULL THEN
+         root_id := new.node_id;
+    END IF;
+
+    SELECT count(*)::int INTO rcount FROM forum_node WHERE id = root_id;
+
+    IF rcount = 0 THEN
+        return new;
+    END IF;
+
+    SELECT
+      setweight(to_tsvector('english', coalesce(tagnames,'')), 'A') ||
+      setweight(to_tsvector('english', coalesce(title,'')), 'B') ||
+      setweight(to_tsvector('english', coalesce(body,'')), 'C') INTO doc
+      FROM forum_node WHERE id = root_id;
+
+    SELECT count(*)::int INTO rcount FROM forum_node WHERE abs_parent_id = root_id AND (NOT state_string LIKE '%%deleted%%');
+
+    IF rcount > 0 THEN
+       FOR cv in SELECT setweight(to_tsvector('english', coalesce(body,'')), 'C') FROM forum_node WHERE abs_parent_id = root_id  AND (NOT state_string LIKE '%%deleted%%') LOOP
+           doc :=(doc || cv);
+       END LOOP;
+     END IF;
+
+    SELECT count(*)::int INTO rcount FROM forum_rootnode_doc WHERE node_id = root_id;
+
+    IF rcount > 0 THEN
+       UPDATE forum_rootnode_doc SET document = doc WHERE node_id = root_id;
+    ELSE
+       INSERT INTO forum_rootnode_doc (node_id, document) VALUES (root_id, doc);
+    END IF;
+
+  RETURN new;
+end
+$$ LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION public.build_doc_table() RETURNS VOID as $$
+  CREATE TABLE forum_rootnode_doc
+  (
+     node_id integer,
+     "document" tsvector,
+      PRIMARY KEY (node_id),
+      FOREIGN KEY (node_id) REFERENCES forum_node (id)    ON UPDATE NO ACTION ON DELETE NO ACTION
+  ) WITH (OIDS=FALSE);
+
+  DROP TRIGGER IF EXISTS tsvectorupdate ON forum_noderevision;
+
+  CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATE
+    ON forum_noderevision FOR EACH ROW EXECUTE PROCEDURE set_doctable_tsv();
+
+  CREATE INDEX doctable_tsv ON forum_rootnode_doc USING gin(document);
+$$ LANGUAGE 'sql';
+
+CREATE OR REPLACE FUNCTION public.doc_table_exists() RETURNS int AS $$
+ SELECT COUNT(table_name)::int FROM information_schema.tables WHERE table_name = 'forum_rootnode_doc';
+$$ LANGUAGE 'sql';
+
+select case when public.doc_table_exists()=0 then public.build_doc_table()end;
+
+drop function build_doc_table();
+drop function doc_table_exists();
+
+CREATE OR REPLACE FUNCTION rank_exact_matches(rank float) RETURNS float AS $$
+begin
+       IF rank = 0 THEN
+               return 1;
+       ELSE
+               return rank;
+       END IF;
+
+end
+$$ LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION public.rebuild_index() RETURNS VOID as $$
+       DECLARE
+               r integer;
+       BEGIN
+               FOR r IN SELECT active_revision_id FROM forum_node WHERE node_type = 'question' LOOP
+                       UPDATE forum_noderevision SET id = id WHERE id = r;
+               END LOOP;
+       END
+$$ LANGUAGE 'plpgsql';
+
+SELECT rebuild_index();
diff --git a/forum/modules/template_loader.py/forum_modules/pgfulltext/settings.py b/forum/modules/template_loader.py/forum_modules/pgfulltext/settings.py
new file mode 100644 (file)
index 0000000..b2f2497
--- /dev/null
@@ -0,0 +1,3 @@
+from forum.settings.base import Setting\r
+\r
+PG_FTSTRIGGERS_VERSION = Setting('PG_FTSTRIGGERS_VERSION', 0)
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/pgfulltext/startup.py b/forum/modules/template_loader.py/forum_modules/pgfulltext/startup.py
new file mode 100644 (file)
index 0000000..d45019f
--- /dev/null
@@ -0,0 +1,27 @@
+import os\r
+from forum.models import KeyValue\r
+from django.db import connection, transaction\r
+import settings\r
+\r
+VERSION = 11\r
+\r
+if int(settings.PG_FTSTRIGGERS_VERSION) < VERSION:\r
+    f = open(os.path.join(os.path.dirname(__file__), 'pg_fts_install.sql'), 'r')\r
+\r
+    try:\r
+        cursor = connection.cursor()\r
+        cursor.execute(f.read())\r
+        transaction.commit_unless_managed()\r
+\r
+        settings.PG_FTSTRIGGERS_VERSION.set_value(VERSION)\r
+        \r
+    except Exception, e:\r
+        #import sys, traceback\r
+        #traceback.print_exc(file=sys.stdout)\r
+        pass\r
+    finally:\r
+        cursor.close()\r
+\r
+    f.close()\r
+\r
+import handlers\r
diff --git a/forum/modules/template_loader.py/forum_modules/project_badges/__init__.py b/forum/modules/template_loader.py/forum_modules/project_badges/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/forum/modules/template_loader.py/forum_modules/project_badges/badges.py b/forum/modules/template_loader.py/forum_modules/project_badges/badges.py
new file mode 100644 (file)
index 0000000..f9b6fbc
--- /dev/null
@@ -0,0 +1,20 @@
+from django.utils.translation import ugettext as _
+from forum.badges.base import AbstractBadge
+from forum.models import Badge, Tag
+from forum.actions import VoteUpAction
+import settings
+
+class BugBuster(AbstractBadge):
+    type = Badge.SILVER
+    name = _("Bug Buster")
+    description = _('Got %s upvotes in a question tagged with "bug"') % settings.BUG_BUSTER_VOTES_UP
+    listen_to = (VoteUpAction, )
+
+    def award_to(self, action):
+        if action.node.node_type == "question" and action.node.score == settings.BUG_BUSTER_VOTES_UP:
+            try:
+                bug = Tag.objects.get(name="bug")
+                if bug in action.node.tags.all():
+                    return action.node.author
+            except:
+                pass
diff --git a/forum/modules/template_loader.py/forum_modules/project_badges/settings.py b/forum/modules/template_loader.py/forum_modules/project_badges/settings.py
new file mode 100644 (file)
index 0000000..375ab7b
--- /dev/null
@@ -0,0 +1,8 @@
+from forum.settings import BADGES_SET
+from forum.settings.base import Setting
+
+BUG_BUSTER_VOTES_UP = Setting('BUG_BUSTER_VOTES_UP', 3, BADGES_SET, dict(
+label = "Bug Buster Votes Up",
+help_text = """
+Number of votes up required for the author of a question tagged as bug to be awarded the Bug Buster badge.
+"""))
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/recaptcha/__init__.py b/forum/modules/template_loader.py/forum_modules/recaptcha/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/forum/modules/template_loader.py/forum_modules/recaptcha/formfield.py b/forum/modules/template_loader.py/forum_modules/recaptcha/formfield.py
new file mode 100644 (file)
index 0000000..88b9497
--- /dev/null
@@ -0,0 +1,32 @@
+from django import forms
+from lib import captcha
+from django.utils.safestring import mark_safe
+from django.utils.encoding import force_unicode, smart_unicode
+from django.utils.translation import ugettext_lazy as _
+import settings
+
+class ReCaptchaField(forms.Field):
+    def __init__(self, *args, **kwargs):
+        super(ReCaptchaField, self).__init__(widget=ReCaptchaWidget)
+
+    def clean(self, values):
+        super(ReCaptchaField, self).clean(values[1])
+        recaptcha_challenge_value = smart_unicode(values[0])
+        recaptcha_response_value = smart_unicode(values[1])
+        check_captcha = captcha.submit(recaptcha_challenge_value,
+            recaptcha_response_value, settings.RECAPTCHA_PRIV_KEY, {})
+
+        if not check_captcha.is_valid:
+            raise forms.util.ValidationError(_('Invalid captcha'))
+            
+        return values[0]
+
+
+class ReCaptchaWidget(forms.Widget):
+    def render(self, name, value, attrs=None):
+        return mark_safe(force_unicode(captcha.displayhtml(settings.RECAPTCHA_PUB_KEY)))
+
+    def value_from_datadict(self, data, files, name):
+        return (data.get('recaptcha_challenge_field', None), data.get('recaptcha_response_field', None))
+        
+
diff --git a/forum/modules/template_loader.py/forum_modules/recaptcha/handlers.py b/forum/modules/template_loader.py/forum_modules/recaptcha/handlers.py
new file mode 100644 (file)
index 0000000..00fc424
--- /dev/null
@@ -0,0 +1,4 @@
+from formfield import ReCaptchaField
+
+def create_anti_spam_field():
+    return ('recaptcha', ReCaptchaField())
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/recaptcha/lib/__init__.py b/forum/modules/template_loader.py/forum_modules/recaptcha/lib/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/forum/modules/template_loader.py/forum_modules/recaptcha/lib/captcha.py b/forum/modules/template_loader.py/forum_modules/recaptcha/lib/captcha.py
new file mode 100644 (file)
index 0000000..03323ee
--- /dev/null
@@ -0,0 +1,96 @@
+import urllib2, urllib
+
+API_SSL_SERVER="https://api-secure.recaptcha.net"
+API_SERVER="http://api.recaptcha.net"
+VERIFY_SERVER="api-verify.recaptcha.net"
+
+class RecaptchaResponse(object):
+    def __init__(self, is_valid, error_code=None):
+        self.is_valid = is_valid
+        self.error_code = error_code
+
+def displayhtml (public_key,
+                 use_ssl = False,
+                 error = None):
+    """Gets the HTML to display for reCAPTCHA
+
+    public_key -- The public api key
+    use_ssl -- Should the request be sent over ssl?
+    error -- An error message to display (from RecaptchaResponse.error_code)"""
+
+    error_param = ''
+    if error:
+        error_param = '&error=%s' % error
+
+    if use_ssl:
+        server = API_SSL_SERVER
+    else:
+        server = API_SERVER
+
+    return """<script type="text/javascript" src="%(ApiServer)s/challenge?k=%(PublicKey)s%(ErrorParam)s"></script>
+
+<noscript>
+  <iframe src="%(ApiServer)s/noscript?k=%(PublicKey)s%(ErrorParam)s" height="300" width="500" frameborder="0"></iframe><br />
+  <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
+  <input type='hidden' name='recaptcha_response_field' value='manual_challenge' />
+</noscript>
+""" % {
+        'ApiServer' : server,
+        'PublicKey' : public_key,
+        'ErrorParam' : error_param,
+        }
+
+
+def submit (recaptcha_challenge_field,
+            recaptcha_response_field,
+            private_key,
+            remoteip):
+    """
+    Submits a reCAPTCHA request for verification. Returns RecaptchaResponse
+    for the request
+
+    recaptcha_challenge_field -- The value of recaptcha_challenge_field from the form
+    recaptcha_response_field -- The value of recaptcha_response_field from the form
+    private_key -- your reCAPTCHA private key
+    remoteip -- the user's ip address
+    """
+
+    if not (recaptcha_response_field and recaptcha_challenge_field and
+            len (recaptcha_response_field) and len (recaptcha_challenge_field)):
+        return RecaptchaResponse (is_valid = False, error_code = 'incorrect-captcha-sol')
+
+
+    def encode_if_necessary(s):
+        if isinstance(s, unicode):
+            return s.encode('utf-8')
+        return s
+
+    params = urllib.urlencode ({
+            'privatekey': encode_if_necessary(private_key),
+            'remoteip' :  encode_if_necessary(remoteip),
+            'challenge':  encode_if_necessary(recaptcha_challenge_field),
+            'response' :  encode_if_necessary(recaptcha_response_field),
+            })
+
+    request = urllib2.Request (
+        url = "http://%s/verify" % VERIFY_SERVER,
+        data = params,
+        headers = {
+            "Content-type": "application/x-www-form-urlencoded",
+            "User-agent": "reCAPTCHA Python"
+            }
+        )
+
+    httpresp = urllib2.urlopen (request)
+
+    return_values = httpresp.read ().splitlines ();
+    httpresp.close();
+
+    return_code = return_values [0]
+
+    if (return_code == "true"):
+        return RecaptchaResponse (is_valid=True)
+    else:
+        return RecaptchaResponse (is_valid=False, error_code = return_values [1])
+
+
diff --git a/forum/modules/template_loader.py/forum_modules/recaptcha/settings.py b/forum/modules/template_loader.py/forum_modules/recaptcha/settings.py
new file mode 100644 (file)
index 0000000..ceeef72
--- /dev/null
@@ -0,0 +1,17 @@
+from forum.settings import EXT_KEYS_SET
+from forum.settings.base import Setting
+
+RECAPTCHA_PUB_KEY = Setting('RECAPTCHA_PUB_KEY', '', EXT_KEYS_SET, dict(
+label = "Recaptch public key",
+help_text = """
+Get this key at <a href="http://recaptcha.net">reCaptcha</a> to enable
+recaptcha anti spam through.
+""",
+required=False))
+
+RECAPTCHA_PRIV_KEY = Setting('RECAPTCHA_PRIV_KEY', '', EXT_KEYS_SET, dict(
+label = "Recaptch private key",
+help_text = """
+This is the private key you'll get in the same place as the recaptcha public key.
+""",
+required=False))
diff --git a/forum/modules/template_loader.py/forum_modules/robotstxt/__init__.py b/forum/modules/template_loader.py/forum_modules/robotstxt/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/forum/modules/template_loader.py/forum_modules/robotstxt/settings.py b/forum/modules/template_loader.py/forum_modules/robotstxt/settings.py
new file mode 100644 (file)
index 0000000..44d576a
--- /dev/null
@@ -0,0 +1,23 @@
+from forum.settings.base import Setting, SettingSet
+from django.forms.widgets import Textarea
+from django.core.urlresolvers import reverse
+from forum.settings import APP_URL
+
+ROBOTS_SET = SettingSet('robots', 'Robots txt', "Set up the robots.txt file.", 3000)
+
+ROBOTS_FILE = Setting('ROBOTS_FILE',
+"""Sitemap: %s/sitemap.xml
+
+User-Agent: *
+Disallow: /accounts/
+Disallow: /users/
+Disallow: /revisions/
+Disallow: /search
+Disallow: /matching_tags
+Disallow: /*sort=
+""" % APP_URL, ROBOTS_SET, dict(
+label = "Robots.txt file",
+help_text = """
+The robots.txt file search engine spiders will see.
+""",
+widget=Textarea(attrs={'rows': '20'})))
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/robotstxt/templates/robots.txt b/forum/modules/template_loader.py/forum_modules/robotstxt/templates/robots.txt
new file mode 100644 (file)
index 0000000..a93756d
--- /dev/null
@@ -0,0 +1,7 @@
+User-Agent: *
+Disallow: /accounts/
+Disallow: /users/
+Disallow: /revisions/
+Disallow: /search
+Disallow: /matching_tags
+Disallow: /*sort=
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/robotstxt/urls.py b/forum/modules/template_loader.py/forum_modules/robotstxt/urls.py
new file mode 100644 (file)
index 0000000..0706886
--- /dev/null
@@ -0,0 +1,7 @@
+from django.conf.urls.defaults import *
+from django.http import  HttpResponse
+import settings
+
+urlpatterns = patterns('',
+    (r'^robots.txt$',  lambda r: HttpResponse(settings.ROBOTS_FILE.value)),
+)
diff --git a/forum/modules/template_loader.py/forum_modules/sphinxfulltext/README.txt b/forum/modules/template_loader.py/forum_modules/sphinxfulltext/README.txt
new file mode 100644 (file)
index 0000000..7d65653
--- /dev/null
@@ -0,0 +1,29 @@
+Full text search (using sphinx search)
+
+Currently full text search works only with sphinx search engine
+And builtin PostgreSQL (postgres only >= 8.3???)
+
+5.1 Instructions for Sphinx search setup
+Sphinx at this time supports only MySQL and PostgreSQL databases
+to enable this, install sphinx search engine and djangosphinx
+
+configure sphinx, sample configuration can be found in
+sphinx/sphinx.conf file usually goes somewhere in /etc tree
+
+build osqa index first time manually
+
+% indexer --config /path/to/sphinx.conf --index osqa
+
+setup cron job to rebuild index periodically with command
+your crontab entry may be something like
+
+0 9,15,21 * * * /usr/local/bin/indexer --config /etc/sphinx/sphinx.conf --all --rotate >/dev/null 2>&1
+adjust it as necessary this one will reindex three times a day at 9am 3pm and 9pm
+
+if your forum grows very big ( good luck with that :) you'll
+need to two search indices one diff index and one main
+please refer to online sphinx search documentation for the information
+on the subject http://sphinxsearch.com/docs/
+
+in settings.py look for INSTALLED_APPS
+and uncomment #'djangosphinx',
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/sphinxfulltext/__init__.py b/forum/modules/template_loader.py/forum_modules/sphinxfulltext/__init__.py
new file mode 100644 (file)
index 0000000..b7250c8
--- /dev/null
@@ -0,0 +1,5 @@
+try:
+    import djangosphinx
+    CAN_USE = True
+except:
+    CAN_USE = False
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/sphinxfulltext/dependencies.py b/forum/modules/template_loader.py/forum_modules/sphinxfulltext/dependencies.py
new file mode 100644 (file)
index 0000000..046ebfc
--- /dev/null
@@ -0,0 +1,2 @@
+DJANGO_APPS = ('djangosphinx', )
+
diff --git a/forum/modules/template_loader.py/forum_modules/sphinxfulltext/handlers.py b/forum/modules/template_loader.py/forum_modules/sphinxfulltext/handlers.py
new file mode 100644 (file)
index 0000000..f00c64f
--- /dev/null
@@ -0,0 +1,4 @@
+from forum.models import Question
+
+def question_search(keywords):
+    return Question.search.query(keywords)
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/sphinxfulltext/models.py b/forum/modules/template_loader.py/forum_modules/sphinxfulltext/models.py
new file mode 100644 (file)
index 0000000..a188728
--- /dev/null
@@ -0,0 +1,11 @@
+from forum.models import Question
+from django.conf import settings
+from djangosphinx.manager import SphinxSearch
+
+from djangosphinx.models import SphinxSearch
+
+Question.add_to_class('search', SphinxSearch(
+                                   index=' '.join(settings.SPHINX_SEARCH_INDICES),
+                                   mode='SPH_MATCH_ALL',
+                                )
+                      )
diff --git a/forum/modules/template_loader.py/forum_modules/sphinxfulltext/settings.py b/forum/modules/template_loader.py/forum_modules/sphinxfulltext/settings.py
new file mode 100644 (file)
index 0000000..7c2da12
--- /dev/null
@@ -0,0 +1,5 @@
+SPHINX_API_VERSION = 0x113 #refer to djangosphinx documentation
+SPHINX_SEARCH_INDICES=('osqa',) #a tuple of index names remember about a comma after the
+#last item, especially if you have just one :)
+SPHINX_SERVER='localhost'
+SPHINX_PORT=3312
diff --git a/forum/modules/template_loader.py/forum_modules/sximporter/__init__.py b/forum/modules/template_loader.py/forum_modules/sximporter/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/forum/modules/template_loader.py/forum_modules/sximporter/importer.py b/forum/modules/template_loader.py/forum_modules/sximporter/importer.py
new file mode 100644 (file)
index 0000000..44f90d7
--- /dev/null
@@ -0,0 +1,1002 @@
+# -*- coding: utf-8 -*-
+
+from xml.dom import minidom
+from datetime import datetime, timedelta
+import time
+import re
+import os
+import gc
+from django.utils.translation import ugettext as _
+from django.template.defaultfilters import slugify
+from forum.models.utils import dbsafe_encode
+from orm import orm
+
+from django.utils.encoding import force_unicode
+
+try:
+    from cPickle import loads, dumps
+except ImportError:
+    from pickle import loads, dumps
+
+from copy import deepcopy
+from base64 import b64encode, b64decode
+from zlib import compress, decompress
+
+from xml.sax import make_parser
+from xml.sax.handler import ContentHandler
+
+class SXTableHandler(ContentHandler):
+    def __init__(self, fname, callback):
+        self.in_row = False
+        self.el_data = {}
+        self.ch_data = ''
+
+        self.fname = fname.lower()
+        self.callback = callback
+
+    def startElement(self, name, attrs):
+        if name.lower() == self.fname:
+            pass
+        elif name.lower() == "row":
+            self.in_row = True
+
+    def characters(self, ch):
+        self.ch_data += ch
+
+    def endElement(self, name):
+        if name.lower() == self.fname:
+            pass
+        elif name.lower() == "row":
+            self.callback(self.el_data)
+
+            self.in_row = False
+            del self.el_data
+            self.el_data = {}
+        elif self.in_row:
+            self.el_data[name.lower()] = self.ch_data.strip()
+            del self.ch_data
+            self.ch_data = ''
+
+
+def readTable(path, name, callback):
+    parser = make_parser()
+    handler = SXTableHandler(name, callback)
+    parser.setContentHandler(handler)
+
+    f = os.path.join(path, "%s.xml" % name)
+    parser.parse(f)
+
+
+def dbsafe_encode(value):
+    return force_unicode(b64encode(compress(dumps(deepcopy(value)))))
+
+def getText(el):
+    rc = ""
+    for node in el.childNodes:
+        if node.nodeType == node.TEXT_NODE:
+            rc = rc + node.data
+    return rc.strip()
+
+msstrip = re.compile(r'^(.*)\.\d+')
+def readTime(ts):
+    noms = msstrip.match(ts)
+    if noms:
+        ts = noms.group(1)
+
+    return datetime(*time.strptime(ts, '%Y-%m-%dT%H:%M:%S')[0:6])
+
+#def readEl(el):
+#    return dict([(n.tagName.lower(), getText(n)) for n in el.childNodes if n.nodeType == el.ELEMENT_NODE])
+
+#def readTable(dump, name):
+#    for e in minidom.parseString(dump.read("%s.xml" % name)).getElementsByTagName('row'):
+#        yield readEl(e)
+#return [readEl(e) for e in minidom.parseString(dump.read("%s.xml" % name)).getElementsByTagName('row')]
+
+google_accounts_lookup = re.compile(r'^https?://www.google.com/accounts/')
+yahoo_accounts_lookup = re.compile(r'^https?://me.yahoo.com/a/')
+
+openid_lookups = [
+        re.compile(r'^https?://www.google.com/profiles/(?P<uname>\w+(\.\w+)*)/?$'),
+        re.compile(r'^https?://me.yahoo.com/(?P<uname>\w+(\.\w+)*)/?$'),
+        re.compile(r'^https?://openid.aol.com/(?P<uname>\w+(\.\w+)*)/?$'),
+        re.compile(r'^https?://(?P<uname>\w+(\.\w+)*).myopenid.com/?$'),
+        re.compile(r'^https?://flickr.com/(\w+/)*(?P<uname>\w+(\.\w+)*)/?$'),
+        re.compile(r'^https?://technorati.com/people/technorati/(?P<uname>\w+(\.\w+)*)/?$'),
+        re.compile(r'^https?://(?P<uname>\w+(\.\w+)*).wordpress.com/?$'),
+        re.compile(r'^https?://(?P<uname>\w+(\.\w+)*).blogspot.com/?$'),
+        re.compile(r'^https?://(?P<uname>\w+(\.\w+)*).livejournal.com/?$'),
+        re.compile(r'^https?://claimid.com/(?P<uname>\w+(\.\w+)*)/?$'),
+        re.compile(r'^https?://(?P<uname>\w+(\.\w+)*).pip.verisignlabs.com/?$'),
+        re.compile(r'^https?://getopenid.com/(?P<uname>\w+(\.\w+)*)/?$'),
+        re.compile(r'^https?://[\w\.]+/(\w+/)*(?P<uname>\w+(\.\w+)*)/?$'),
+        re.compile(r'^https?://(?P<uname>[\w\.]+)/?$'),
+        ]
+
+def final_username_attempt(sxu):
+    openid = sxu.get('openid', None)
+
+    if openid:
+        if google_accounts_lookup.search(openid):
+            return UnknownGoogleUser(sxu.get('id'))
+        if yahoo_accounts_lookup.search(openid):
+            return UnknownYahooUser(sxu.get('id'))
+
+        for lookup in openid_lookups:
+            if lookup.search(openid):
+                return lookup.search(openid).group('uname')
+
+    return UnknownUser(sxu.get('id'))
+
+class UnknownUser(object):
+    def __init__(self, id):
+        self._id = id
+
+    def __str__(self):
+        return _("user-%(id)s") % {'id': self._id}
+
+    def __unicode__(self):
+        return self.__str__()
+
+    def encode(self, *args):
+        return self.__str__()
+
+class UnknownGoogleUser(UnknownUser):
+    def __str__(self):
+        return _("user-%(id)s (google)") % {'id': self._id}
+
+class UnknownYahooUser(UnknownUser):
+    def __str__(self):
+        return _("user-%(id)s (yahoo)") % {'id': self._id}
+
+
+class IdMapper(dict):
+    def __getitem__(self, key):
+        key = int(key)
+        return super(IdMapper, self).get(key, 1)
+
+    def __setitem__(self, key, value):
+        super(IdMapper, self).__setitem__(int(key), int(value))
+
+class IdIncrementer():
+    def __init__(self, initial):
+        self.value = initial
+
+    def inc(self):
+        self.value += 1
+
+openidre = re.compile('^https?\:\/\/')
+def userimport(path, options):
+#users = readTable(dump, "Users")
+
+    usernames = []
+    openids = set()
+    uidmapper = IdMapper()
+    #merged_users = []
+
+    owneruid = options.get('owneruid', None)
+    #check for empty values
+    if not owneruid:
+        owneruid = None
+
+    def callback(sxu):
+        create = True
+
+        if sxu.get('id') == '-1':
+            return
+        #print "\n".join(["%s : %s" % i for i in sxu.items()])
+        if int(sxu.get('id')) == int(owneruid):
+            osqau = orm.User.objects.get(id=1)
+            for assoc in orm.AuthKeyUserAssociation.objects.filter(user=osqau):
+                openids.add(assoc.key)
+            uidmapper[owneruid] = 1
+            uidmapper[-1] = 1
+            create = False
+        else:
+            username = unicode(sxu.get('displayname',
+                               sxu.get('displaynamecleaned', sxu.get('realname', final_username_attempt(sxu)))))[:30]
+
+            if username in usernames:
+            #if options.get('mergesimilar', False) and sxu.get('email', 'INVALID') == user_by_name[username].email:
+            #    osqau = user_by_name[username]
+            #    create = False
+            #    uidmapper[sxu.get('id')] = osqau.id
+            #else:
+                inc = 0
+
+                while True:
+                    inc += 1
+                    totest = "%s %d" % (username[:29 - len(str(inc))], inc)
+
+                    if not totest in usernames:
+                        username = totest
+                        break          
+
+        sxbadges = sxu.get('badgesummary', None)
+        badges = {'1':'0', '2':'0', '3':'0'}
+
+        if sxbadges:
+            badges.update(dict([b.split('=') for b in sxbadges.split()]))
+
+        if create:
+            osqau = orm.User(
+                    id           = sxu.get('id'),
+                    username     = username,
+                    password     = '!',
+                    email        = sxu.get('email', ''),
+                    is_superuser = sxu.get('usertypeid') == '5',
+                    is_staff     = sxu.get('usertypeid') == '4',
+                    is_active    = True,
+                    date_joined  = readTime(sxu.get('creationdate')),
+                    last_seen    = readTime(sxu.get('lastaccessdate')),
+                    about         = sxu.get('aboutme', ''),
+                    date_of_birth = sxu.get('birthday', None) and readTime(sxu['birthday']) or None,
+                    email_isvalid = int(sxu.get('usertypeid')) > 2,
+                    website       = sxu.get('websiteurl', ''),
+                    reputation    = int(sxu.get('reputation')),
+                    gold          = int(badges['1']),
+                    silver        = int(badges['2']),
+                    bronze        = int(badges['3']),
+                    real_name     = sxu.get('realname', '')[:30],
+                    location      = sxu.get('location', ''),
+                    )
+
+            osqau.save()
+
+            user_joins = orm.Action(
+                    action_type = "userjoins",
+                    action_date = osqau.date_joined,
+                    user = osqau
+                    )
+            user_joins.save()
+
+            rep = orm.ActionRepute(
+                    value = 1,
+                    user = osqau,
+                    date = osqau.date_joined,
+                    action = user_joins
+                    )
+            rep.save()
+
+            try:
+                orm.SubscriptionSettings.objects.get(user=osqau)
+            except:
+                s = orm.SubscriptionSettings(user=osqau)
+                s.save()
+
+            uidmapper[osqau.id] = osqau.id
+        else:
+            new_about = sxu.get('aboutme', None)
+            if new_about and osqau.about != new_about:
+                if osqau.about:
+                    osqau.about = "%s\n|\n%s" % (osqau.about, new_about)
+                else:
+                    osqau.about = new_about
+
+            osqau.username = sxu.get('displayname',
+                                     sxu.get('displaynamecleaned', sxu.get('realname', final_username_attempt(sxu))))
+            osqau.email = sxu.get('email', '')
+            osqau.reputation += int(sxu.get('reputation'))
+            osqau.gold += int(badges['1'])
+            osqau.silver += int(badges['2'])
+            osqau.bronze += int(badges['3'])
+
+            osqau.date_joined = readTime(sxu.get('creationdate'))
+            osqau.website = sxu.get('websiteurl', '')
+            osqau.date_of_birth = sxu.get('birthday', None) and readTime(sxu['birthday']) or None
+            osqau.location = sxu.get('location', '')
+            osqau.real_name = sxu.get('realname', '')
+
+            #merged_users.append(osqau.id)
+            osqau.save()
+
+        usernames.append(osqau.username)
+
+        openid = sxu.get('openid', None)
+        if openid and openidre.match(openid) and (not openid in openids):
+            assoc = orm.AuthKeyUserAssociation(user=osqau, key=openid, provider="openidurl")
+            assoc.save()
+            openids.add(openid)
+
+        openidalt = sxu.get('openidalt', None)
+        if openidalt and openidre.match(openidalt) and (not openidalt in openids):
+            assoc = orm.AuthKeyUserAssociation(user=osqau, key=openidalt, provider="openidurl")
+            assoc.save()
+            openids.add(openidalt)
+
+    readTable(path, "Users", callback)
+
+    if uidmapper[-1] == -1:
+        uidmapper[-1] = 1
+
+    return uidmapper
+
+def tagsimport(dump, uidmap):
+#tags = readTable(dump, "Tags")
+
+    tagmap = {}
+
+    def callback(sxtag):
+        otag = orm.Tag(
+                id = int(sxtag['id']),
+                name = sxtag['name'],
+                used_count = int(sxtag['count']),
+                created_by_id = uidmap[sxtag.get('userid', 1)],
+                )
+        otag.save()
+
+        tagmap[otag.name] = otag
+
+    readTable(dump, "Tags", callback)
+
+    return tagmap
+
+def add_post_state(name, post, action):
+    if not "(%s)" % name in post.state_string:
+        post.state_string = "%s(%s)" % (post.state_string, name)
+        post.save()
+
+    try:
+        state = orm.NodeState.objects.get(node=post, state_type=name)
+        state.action = action
+        state.save()
+    except:
+        state = orm.NodeState(node=post, state_type=name, action=action)
+        state.save()
+
+def remove_post_state(name, post):
+    if "(%s)" % name in post.state_string:
+        try:
+            state = orm.NodeState.objects.get(state_type=name, post=post)
+            state.delete()
+        except:
+            pass
+    post.state_string = "".join("(%s)" % s for s in re.findall('\w+', post.state_string) if s != name)
+
+def postimport(dump, uidmap, tagmap):
+#history = {}
+#accepted = {}
+    all = []
+
+    #for h in readTable(dump, "PostHistory"):
+    #    if not history.get(h.get('postid'), None):
+    #        history[h.get('postid')] = []
+    #
+    #    history[h.get('postid')].append(h)
+
+    #posts = readTable(dump, "Posts")
+
+    def callback(sxpost):
+        nodetype = (sxpost.get('posttypeid') == '1') and "nodetype" or "answer"
+
+        post = orm.Node(
+                node_type = nodetype,
+                id = sxpost['id'],
+                added_at = readTime(sxpost['creationdate']),
+                body = sxpost['body'],
+                score = sxpost.get('score', 0),
+                author_id = sxpost.get('deletiondate', None) and 1 or uidmap[sxpost.get('owneruserid', 1)]
+                )
+
+        post.save()
+
+        create_action = orm.Action(
+                action_type = (nodetype == "nodetype") and "ask" or "answer",
+                user_id = post.author_id,
+                node = post,
+                action_date = post.added_at
+                )
+
+        create_action.save()
+
+        if sxpost.get('lasteditoruserid', None):
+            revise_action = orm.Action(
+                    action_type = "revise",
+                    user_id = uidmap[sxpost.get('lasteditoruserid')],
+                    node = post,
+                    action_date = readTime(sxpost['lasteditdate']),
+                    )
+
+            revise_action.save()
+            post.last_edited = revise_action
+
+        if sxpost.get('communityowneddate', None):
+            wikify_action = orm.Action(
+                    action_type = "wikify",
+                    user_id = 1,
+                    node = post,
+                    action_date = readTime(sxpost['communityowneddate'])
+                    )
+
+            wikify_action.save()
+            add_post_state("wiki", post, wikify_action)
+
+        if sxpost.get('lastactivityuserid', None):
+            post.last_activity_by_id = uidmap[sxpost['lastactivityuserid']]
+            post.last_activity_at = readTime(sxpost['lastactivitydate'])
+
+        if sxpost.get('posttypeid') == '1': #question
+            post.node_type = "question"
+            post.title = sxpost['title']
+
+            tagnames = sxpost['tags'].replace(u'ö', '-').replace(u'é', '').replace(u'à', '')
+            post.tagnames = tagnames
+
+            post.extra_count = sxpost.get('viewcount', 0)
+
+            add_tags_to_post(post, tagmap)
+
+        else:
+            post.parent_id = sxpost['parentid']
+
+        post.save()
+
+        all.append(int(post.id))
+
+        del post
+
+    readTable(dump, "Posts", callback)
+
+    return all
+
+def comment_import(dump, uidmap, posts):
+#comments = readTable(dump, "PostComments")
+    currid = IdIncrementer(max(posts))
+    mapping = {}
+
+    def callback(sxc):
+        currid.inc()
+        oc = orm.Node(
+                id = currid.value,
+                node_type = "comment",
+                added_at = readTime(sxc['creationdate']),
+                author_id = uidmap[sxc.get('userid', 1)],
+                body = sxc['text'],
+                parent_id = sxc.get('postid'),
+                )
+
+        if sxc.get('deletiondate', None):
+            delete_action = orm.Action(
+                    action_type = "delete",
+                    user_id = uidmap[sxc['deletionuserid']],
+                    action_date = readTime(sxc['deletiondate'])
+                    )
+
+            oc.author_id = uidmap[sxc['deletionuserid']]
+            oc.save()
+
+            delete_action.node = oc
+            delete_action.save()
+
+            add_post_state("deleted", oc, delete_action)
+        else:
+            oc.author_id = uidmap[sxc.get('userid', 1)]
+            oc.save()
+
+        create_action = orm.Action(
+                action_type = "comment",
+                user_id = oc.author_id,
+                node = oc,
+                action_date = oc.added_at
+                )
+
+        create_action.save()
+        oc.save()
+
+        posts.append(int(oc.id))
+        mapping[int(sxc['id'])] = int(oc.id)
+
+    readTable(dump, "PostComments", callback)
+    return posts, mapping
+
+
+def add_tags_to_post(post, tagmap):
+    tags = [tag for tag in [tagmap.get(name.strip()) for name in post.tagnames.split(u' ') if name] if tag]
+    post.tagnames = " ".join([t.name for t in tags]).strip()
+    post.tags = tags
+    create_and_activate_revision(post)
+
+
+def create_and_activate_revision(post):
+    rev = orm.NodeRevision(
+            author_id = post.author_id,
+            body = post.body,
+            node_id = post.id,
+            revised_at = post.added_at,
+            revision = 1,
+            summary = 'Initial revision',
+            tagnames = post.tagnames,
+            title = post.title,
+            )
+
+    rev.save()
+    post.active_revision_id = rev.id
+    post.save()
+
+def post_vote_import(dump, uidmap, posts):
+#votes = readTable(dump, "Posts2Votes")
+    close_reasons = {}
+
+    def close_callback(r):
+        close_reasons[r['id']] = r['name']
+
+    readTable(dump, "CloseReasons", close_callback)
+
+    user2vote = []
+
+    def callback(sxv):
+        action = orm.Action(
+                user_id=uidmap[sxv['userid']],
+                action_date = readTime(sxv['creationdate']),
+                )
+
+        if not int(sxv['postid']) in posts: return
+        node = orm.Node.objects.get(id=sxv['postid'])
+        action.node = node
+
+        if sxv['votetypeid'] == '1':
+            answer = node
+            question = orm.Node.objects.get(id=answer.parent_id)
+
+            action.action_type = "acceptanswer"
+            action.save()
+
+            answer.marked = True
+
+            question.extra_ref_id = answer.id
+
+            answer.save()
+            question.save()
+
+        elif sxv['votetypeid'] in ('2', '3'):
+            if not (action.node.id, action.user_id) in user2vote:
+                user2vote.append((action.node.id, action.user_id))
+
+                action.action_type = (sxv['votetypeid'] == '2') and "voteup" or "votedown"
+                action.save()
+
+                ov = orm.Vote(
+                        node_id = action.node.id,
+                        user_id = action.user_id,
+                        voted_at = action.action_date,
+                        value = sxv['votetypeid'] == '2' and 1 or -1,
+                        action = action
+                        )
+                ov.save()
+            else:
+                action.action_type = "unknown"
+                action.save()
+
+        elif sxv['votetypeid'] in ('4', '12', '13'):
+            action.action_type = "flag"
+            action.save()
+
+            of = orm.Flag(
+                    node = action.node,
+                    user_id = action.user_id,
+                    flagged_at = action.action_date,
+                    reason = '',
+                    action = action
+                    )
+
+            of.save()
+
+        elif sxv['votetypeid'] == '5':
+            action.action_type = "favorite"
+            action.save()
+
+        elif sxv['votetypeid'] == '6':
+            action.action_type = "close"
+            action.extra = dbsafe_encode(close_reasons[sxv['comment']])
+            action.save()
+
+            node.marked = True
+            node.save()
+
+        elif sxv['votetypeid'] == '7':
+            action.action_type = "unknown"
+            action.save()
+
+            node.marked = False
+            node.save()
+
+            remove_post_state("closed", node)
+
+        elif sxv['votetypeid'] == '10':
+            action.action_type = "delete"
+            action.save()
+
+        elif sxv['votetypeid'] == '11':
+            action.action_type = "unknown"
+            action.save()
+
+            remove_post_state("deleted", node)
+
+        else:
+            action.action_type = "unknown"
+            action.save()
+
+        if sxv.get('targetrepchange', None):
+            rep = orm.ActionRepute(
+                    action = action,
+                    date = action.action_date,
+                    user_id = uidmap[sxv['targetuserid']],
+                    value = int(sxv['targetrepchange'])
+                    )
+
+            rep.save()
+
+        if sxv.get('voterrepchange', None):
+            rep = orm.ActionRepute(
+                    action = action,
+                    date = action.action_date,
+                    user_id = uidmap[sxv['userid']],
+                    value = int(sxv['voterrepchange'])
+                    )
+
+            rep.save()
+
+        if action.action_type in ("acceptanswer", "delete", "close"):
+            state = {"acceptanswer": "accepted", "delete": "deleted", "close": "closed"}[action.action_type]
+            add_post_state(state, node, action)
+
+    readTable(dump, "Posts2Votes", callback)
+
+
+def comment_vote_import(dump, uidmap, comments):
+#votes = readTable(dump, "Comments2Votes")
+    user2vote = []
+    comments2score = {}
+
+    def callback(sxv):
+        if sxv['votetypeid'] == "2":
+            comment_id = comments[int(sxv['postcommentid'])]
+            user_id = uidmap[sxv['userid']]
+
+            if not (comment_id, user_id) in user2vote:
+                user2vote.append((comment_id, user_id))
+
+                action = orm.Action(
+                        action_type = "voteupcomment",
+                        user_id = user_id,
+                        action_date = readTime(sxv['creationdate']),
+                        node_id = comment_id
+                        )
+                action.save()
+
+                ov = orm.Vote(
+                        node_id = comment_id,
+                        user_id = user_id,
+                        voted_at = action.action_date,
+                        value = 1,
+                        action = action
+                        )
+
+                ov.save()
+
+                if not comment_id in comments2score:
+                    comments2score[comment_id] = 1
+                else:
+                    comments2score[comment_id] += 1
+
+    readTable(dump, "Comments2Votes", callback)
+
+    for cid, score in comments2score.items():
+        orm.Node.objects.filter(id=cid).update(score=score)
+
+
+def badges_import(dump, uidmap, post_list):
+#node_ctype = orm['contenttypes.contenttype'].objects.get(name='node')
+
+    sxbadges = {}
+
+    def sxcallback(b):
+        sxbadges[int(b['id'])] = b
+
+    readTable(dump, "Badges", sxcallback)
+
+    obadges = dict([(b.cls, b) for b in orm.Badge.objects.all()])
+    user_badge_count = {}
+
+    sx_to_osqa = {}
+
+    for id, sxb in sxbadges.items():
+        cls = "".join(sxb['name'].replace('&', 'And').split(' '))
+
+        if cls in obadges:
+            sx_to_osqa[id] = obadges[cls]
+        else:
+            osqab = orm.Badge(
+                    cls = cls,
+                    awarded_count = 0,
+                    type = sxb['class']
+                    )
+            osqab.save()
+            sx_to_osqa[id] = osqab
+
+    osqaawards = []
+
+    def callback(sxa):
+        badge = sx_to_osqa[int(sxa['badgeid'])]
+
+        user_id = uidmap[sxa['userid']]
+        if not user_badge_count.get(user_id, None):
+            user_badge_count[user_id] = 0
+
+        action = orm.Action(
+                action_type = "award",
+                user_id = user_id,
+                action_date = readTime(sxa['date'])
+                )
+
+        action.save()
+
+        osqaa = orm.Award(
+                user_id = uidmap[sxa['userid']],
+                badge = badge,
+                node_id = post_list[user_badge_count[user_id]],
+                awarded_at = action.action_date,
+                action = action
+                )
+
+        osqaa.save()
+        badge.awarded_count += 1
+        user_badge_count[user_id] += 1
+
+    readTable(dump, "Users2Badges", callback)
+
+    for badge in obadges.values():
+        badge.save()
+
+def pages_import(dump, currid):
+    currid = IdIncrementer(currid)
+    registry = {}
+    #sx_pages = readTable(dump, "FlatPages")
+
+    def callback(sxp):
+        currid.inc()
+        page = orm.Node(
+                id = currid.value,
+                node_type = "page",
+                title = sxp['name'],
+                body = b64decode(sxp['value']),
+                extra = dbsafe_encode({
+                'path': sxp['url'][1:],
+                'mimetype': sxp['contenttype'],
+                'template': (sxp['usemaster'] == "true") and "default" or "none",
+                'render': "html",
+                'sidebar': "",
+                'sidebar_wrap': True,
+                'sidebar_render': "html",
+                'comments': False
+                }),
+                author_id = 1
+                )
+
+        page.save()
+        registry[sxp['url'][1:]] = page.id
+
+        create_action = orm.Action(
+                action_type = "newpage",
+                user_id = page.author_id,
+                node = page
+                )
+
+        create_action.save()
+
+        if sxp['active'] == "true" and sxp['contenttype'] == "text/html":
+            pub_action = orm.Action(
+                    action_type = "publish",
+                    user_id = page.author_id,
+                    node = page
+                    )
+
+            pub_action.save()
+            add_post_state("published", page, pub_action)
+
+    readTable(dump, "FlatPages", callback)
+
+    kv = orm.KeyValue(key='STATIC_PAGE_REGISTRY', value=dbsafe_encode(registry))
+    kv.save()
+
+sx2osqa_set_map = {
+u'theme.html.name': 'APP_TITLE',
+u'theme.html.footer': 'CUSTOM_FOOTER',
+u'theme.html.sidebar': 'SIDEBAR_UPPER_TEXT',
+u'theme.html.sidebar-low': 'SIDEBAR_LOWER_TEXT',
+u'theme.html.welcome': 'APP_INTRO',
+u'theme.html.head': 'CUSTOM_HEAD',
+u'theme.html.header': 'CUSTOM_HEADER',
+u'theme.css': 'CUSTOM_CSS',
+}
+
+html_codes = (
+('&amp;', '&'),
+('&lt;', '<'),
+('&gt;', '>'),
+('&quot;', '"'),
+('&#39;', "'"),
+)
+
+def html_decode(html):
+    html = force_unicode(html)
+
+    for args in html_codes:
+        html = html.replace(*args)
+
+    return html
+
+
+def static_import(dump):
+#sx_sets = readTable(dump, "ThemeTextResources")
+    sx_unknown = {}
+
+    def callback(set):
+        if unicode(set['name']) in sx2osqa_set_map:
+            try:
+                kv = orm.KeyValue.objects.get(key=sx2osqa_set_map[set['name']])
+                kv.value = dbsafe_encode(html_decode(set['value']))
+            except:
+                kv = orm.KeyValue(
+                        key = sx2osqa_set_map[set['name']],
+                        value = dbsafe_encode(html_decode(set['value']))
+                        )
+
+            kv.save()
+        else:
+            sx_unknown[set['name']] = html_decode(set['value'])
+
+    readTable(dump, "ThemeTextResources", callback)
+
+    unknown = orm.KeyValue(key='SXIMPORT_UNKNOWN_SETS', value=dbsafe_encode(sx_unknown))
+    unknown.save()
+
+def disable_triggers():
+    from south.db import db
+    if db.backend_name == "postgres":
+        db.execute_many(PG_DISABLE_TRIGGERS)
+        db.commit_transaction()
+        db.start_transaction()
+
+def enable_triggers():
+    from south.db import db
+    if db.backend_name == "postgres":
+        db.start_transaction()
+        db.execute_many(PG_ENABLE_TRIGGERS)
+        db.commit_transaction()
+
+def reset_sequences():
+    from south.db import db
+    if db.backend_name == "postgres":
+        db.start_transaction()
+        db.execute_many(PG_SEQUENCE_RESETS)
+        db.commit_transaction()
+
+def reindex_fts():
+    from south.db import db
+    if db.backend_name == "postgres":
+        db.start_transaction()
+        db.execute_many("UPDATE forum_noderevision set id = id WHERE TRUE;")
+        db.commit_transaction()
+
+
+def sximport(dump, options):
+    try:
+        disable_triggers()
+        triggers_disabled = True
+    except:
+        triggers_disabled = False
+
+    uidmap = userimport(dump, options)
+    tagmap = tagsimport(dump, uidmap)
+    gc.collect()
+
+    posts = postimport(dump, uidmap, tagmap)
+    gc.collect()
+
+    posts, comments = comment_import(dump, uidmap, posts)
+    gc.collect()
+
+    post_vote_import(dump, uidmap, posts)
+    gc.collect()
+
+    comment_vote_import(dump, uidmap, comments)
+    gc.collect()
+
+    badges_import(dump, uidmap, posts)
+
+    pages_import(dump, max(posts))
+    static_import(dump)
+    gc.collect()
+
+    from south.db import db
+    db.commit_transaction()
+
+    reset_sequences()
+
+    if triggers_disabled:
+        enable_triggers()
+        reindex_fts()
+
+
+PG_DISABLE_TRIGGERS = """
+ALTER table auth_user DISABLE TRIGGER ALL;
+ALTER table auth_user_groups DISABLE TRIGGER ALL;
+ALTER table auth_user_user_permissions DISABLE TRIGGER ALL;
+ALTER table forum_keyvalue DISABLE TRIGGER ALL;
+ALTER table forum_action DISABLE TRIGGER ALL;
+ALTER table forum_actionrepute DISABLE TRIGGER ALL;
+ALTER table forum_subscriptionsettings DISABLE TRIGGER ALL;
+ALTER table forum_validationhash DISABLE TRIGGER ALL;
+ALTER table forum_authkeyuserassociation DISABLE TRIGGER ALL;
+ALTER table forum_tag DISABLE TRIGGER ALL;
+ALTER table forum_markedtag DISABLE TRIGGER ALL;
+ALTER table forum_node DISABLE TRIGGER ALL;
+ALTER table forum_nodestate DISABLE TRIGGER ALL;
+ALTER table forum_node_tags DISABLE TRIGGER ALL;
+ALTER table forum_noderevision DISABLE TRIGGER ALL;
+ALTER table forum_node_tags DISABLE TRIGGER ALL;
+ALTER table forum_questionsubscription DISABLE TRIGGER ALL;
+ALTER table forum_vote DISABLE TRIGGER ALL;
+ALTER table forum_flag DISABLE TRIGGER ALL;
+ALTER table forum_badge DISABLE TRIGGER ALL;
+ALTER table forum_award DISABLE TRIGGER ALL;
+ALTER table forum_openidnonce DISABLE TRIGGER ALL;
+ALTER table forum_openidassociation DISABLE TRIGGER ALL;
+"""
+
+PG_ENABLE_TRIGGERS = """
+ALTER table auth_user ENABLE TRIGGER ALL;
+ALTER table auth_user_groups ENABLE TRIGGER ALL;
+ALTER table auth_user_user_permissions ENABLE TRIGGER ALL;
+ALTER table forum_keyvalue ENABLE TRIGGER ALL;
+ALTER table forum_action ENABLE TRIGGER ALL;
+ALTER table forum_actionrepute ENABLE TRIGGER ALL;
+ALTER table forum_subscriptionsettings ENABLE TRIGGER ALL;
+ALTER table forum_validationhash ENABLE TRIGGER ALL;
+ALTER table forum_authkeyuserassociation ENABLE TRIGGER ALL;
+ALTER table forum_tag ENABLE TRIGGER ALL;
+ALTER table forum_markedtag ENABLE TRIGGER ALL;
+ALTER table forum_node ENABLE TRIGGER ALL;
+ALTER table forum_nodestate ENABLE TRIGGER ALL;
+ALTER table forum_node_tags ENABLE TRIGGER ALL;
+ALTER table forum_noderevision ENABLE TRIGGER ALL;
+ALTER table forum_node_tags ENABLE TRIGGER ALL;
+ALTER table forum_questionsubscription ENABLE TRIGGER ALL;
+ALTER table forum_vote ENABLE TRIGGER ALL;
+ALTER table forum_flag ENABLE TRIGGER ALL;
+ALTER table forum_badge ENABLE TRIGGER ALL;
+ALTER table forum_award ENABLE TRIGGER ALL;
+ALTER table forum_openidnonce ENABLE TRIGGER ALL;
+ALTER table forum_openidassociation ENABLE TRIGGER ALL;
+"""
+
+PG_SEQUENCE_RESETS = """
+SELECT setval('"auth_user_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "auth_user";
+SELECT setval('"auth_user_groups_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "auth_user_groups";
+SELECT setval('"auth_user_user_permissions_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "auth_user_user_permissions";
+SELECT setval('"forum_keyvalue_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_keyvalue";
+SELECT setval('"forum_action_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_action";
+SELECT setval('"forum_actionrepute_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_actionrepute";
+SELECT setval('"forum_subscriptionsettings_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_subscriptionsettings";
+SELECT setval('"forum_validationhash_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_validationhash";
+SELECT setval('"forum_authkeyuserassociation_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_authkeyuserassociation";
+SELECT setval('"forum_tag_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_tag";
+SELECT setval('"forum_markedtag_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_markedtag";
+SELECT setval('"forum_node_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_node";
+SELECT setval('"forum_nodestate_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_nodestate";
+SELECT setval('"forum_node_tags_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_node_tags";
+SELECT setval('"forum_noderevision_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_noderevision";
+SELECT setval('"forum_node_tags_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_node_tags";
+SELECT setval('"forum_questionsubscription_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_questionsubscription";
+SELECT setval('"forum_vote_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_vote";
+SELECT setval('"forum_flag_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_flag";
+SELECT setval('"forum_badge_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_badge";
+SELECT setval('"forum_award_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_award";
+SELECT setval('"forum_openidnonce_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_openidnonce";
+SELECT setval('"forum_openidassociation_id_seq"', coalesce(max("id"), 1) + 2, max("id") IS NOT null) FROM "forum_openidassociation";
+"""
+
+
+    
+    
diff --git a/forum/modules/template_loader.py/forum_modules/sximporter/orm.py b/forum/modules/template_loader.py/forum_modules/sximporter/orm.py
new file mode 100644 (file)
index 0000000..ff23c85
--- /dev/null
@@ -0,0 +1,265 @@
+from south.v2 import DataMigration\r
+from south.orm import FakeORM\r
+\r
+class Migration(DataMigration):\r
+    def forwards(self, orm):\r
+        pass\r
+\r
+\r
+    def backwards(self, orm):\r
+        "Write your backwards methods here."\r
+\r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.action': {\r
+            'Meta': {'object_name': 'Action'},\r
+            'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),\r
+            'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'real_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'proxied_actions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.actionrepute': {\r
+            'Meta': {'object_name': 'ActionRepute'},\r
+            'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}),\r
+            'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('user', 'badge', 'node'),)", 'object_name': 'Award'},\r
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'award'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.Badge']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'trigger': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'object_name': 'Badge'},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'symmetrical': 'False', 'through': "orm['forum.Award']", 'to': "orm['forum.User']"}),\r
+            'cls': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.flag': {\r
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Flag'},\r
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'flag'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flags'", 'to': "orm['forum.Node']"}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flags'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}),\r
+            'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}),\r
+            'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'state_string': ('django.db.models.fields.TextField', [], {'default': "''"}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'symmetrical': 'False', 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.nodestate': {\r
+            'Meta': {'unique_together': "(('node', 'state_type'),)", 'object_name': 'NodeState'},\r
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'node_state'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'states'", 'to': "orm['forum.Node']"}),\r
+            'state_type': ('django.db.models.fields.CharField', [], {'max_length': '16'})\r
+        },\r
+        'forum.openidassociation': {\r
+            'Meta': {'object_name': 'OpenIdAssociation'},\r
+            'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}),\r
+            'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'issued': ('django.db.models.fields.IntegerField', [], {}),\r
+            'lifetime': ('django.db.models.fields.IntegerField', [], {}),\r
+            'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}),\r
+            'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'})\r
+        },\r
+        'forum.openidnonce': {\r
+            'Meta': {'object_name': 'OpenIdNonce'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),\r
+            'timestamp': ('django.db.models.fields.IntegerField', [], {})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 7, 1, 13, 6, 46, 789996)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'send_digest': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag'},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'symmetrical': 'False', 'through': "orm['forum.MarkedTag']", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'symmetrical': 'False', 'through': "orm['forum.QuestionSubscription']", 'to': "orm['forum.Node']"}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.userproperty': {\r
+            'Meta': {'unique_together': "(('user', 'key'),)", 'object_name': 'UserProperty'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'properties'", 'to': "orm['forum.User']"}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 7, 2, 13, 6, 46, 883626)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Vote'},\r
+            'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'vote'", 'unique': 'True', 'to': "orm['forum.Action']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+\r
+    complete_apps = ['forum']\r
+\r
+orm = FakeORM(Migration, "forum")\r
+\r
diff --git a/forum/modules/template_loader.py/forum_modules/sximporter/templates/page.html b/forum/modules/template_loader.py/forum_modules/sximporter/templates/page.html
new file mode 100644 (file)
index 0000000..0011d1d
--- /dev/null
@@ -0,0 +1,27 @@
+{% extends "osqaadmin/base.html" %}\r
+\r
+{% load i18n %}\r
+{% load user_tags %}\r
+\r
+{% block subtitle %}\r
+    {% trans "SX Importer" %}\r
+{% endblock %}\r
+{% block description %}\r
+    {% trans "Welcome to Stack Exchange dump importer." %}\r
+{% endblock %}\r
+\r
+{% block admincontent %}\r
+    <form method="post" action="" enctype="multipart/form-data">\r
+    <input type="file" name="dump" /><br>\r
+    {% trans "Your user id in stack exchange" %}\r
+    <input type="test" name="owneruid" size="3" value="2" /><br />\r
+\r
+    <input type="checkbox" checked="checked" name="mergesimilar" />\r
+    {% trans "Merge users with same user name and email" %}<br />\r
+\r
+    <input type="submit" value="submit" />\r
+    </form>\r
+    {% for n in names %}\r
+        <p>{{ n }}</p>\r
+    {% endfor %}\r
+{% endblock %}
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/sximporter/urls.py b/forum/modules/template_loader.py/forum_modules/sximporter/urls.py
new file mode 100644 (file)
index 0000000..85fa636
--- /dev/null
@@ -0,0 +1,9 @@
+from django.conf.urls.defaults import *\r
+from django.views.generic.simple import direct_to_template\r
+from django.utils.translation import ugettext as _\r
+\r
+from views import sximporter\r
+\r
+urlpatterns = patterns('',\r
+    url(r'^%s%s$' % (_('admin/'), _('sximporter/')),  sximporter, name='sximporter'),\r
+)
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/forum_modules/sximporter/views.py b/forum/modules/template_loader.py/forum_modules/sximporter/views.py
new file mode 100644 (file)
index 0000000..dcca241
--- /dev/null
@@ -0,0 +1,30 @@
+from django.shortcuts import render_to_response\r
+from django.template import RequestContext\r
+from forum.views.admin import super_user_required\r
+import importer\r
+from zipfile import ZipFile\r
+import os\r
+\r
+@super_user_required\r
+def sximporter(request):\r
+    list = []\r
+    if request.method == "POST" and "dump" in request.FILES:\r
+        dump = ZipFile(request.FILES['dump'])\r
+        members = [f for f in dump.namelist() if f.endswith('.xml')]\r
+        extract_to = os.path.join(os.path.dirname(__file__), 'tmp')\r
+\r
+        if not os.path.exists(extract_to):\r
+            os.makedirs(extract_to)\r
+\r
+        for m in members:\r
+            f = open(os.path.join(extract_to, m), 'w')\r
+            f.write(dump.read(m))\r
+            f.close()\r
+\r
+        #dump.extractall(extract_to, members)\r
+        dump.close()\r
+        importer.sximport(extract_to, request.POST)\r
+\r
+    return render_to_response('modules/sximporter/page.html', {\r
+    'names': list\r
+    }, context_instance=RequestContext(request))\r
diff --git a/forum/modules/template_loader.py/locale/bg/LC_MESSAGES/django.mo b/forum/modules/template_loader.py/locale/bg/LC_MESSAGES/django.mo
new file mode 100755 (executable)
index 0000000..31395ed
Binary files /dev/null and b/forum/modules/template_loader.py/locale/bg/LC_MESSAGES/django.mo differ
diff --git a/forum/modules/template_loader.py/locale/bg/LC_MESSAGES/django.po b/forum/modules/template_loader.py/locale/bg/LC_MESSAGES/django.po
new file mode 100755 (executable)
index 0000000..5839f56
--- /dev/null
@@ -0,0 +1,9070 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2011-01-28 23:44+0200\n"
+"PO-Revision-Date: 2010-12-08 23:13\n"
+"Last-Translator: <jordan.jambazov@gmail.com>\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"
+"X-Translated-Using: django-rosetta 0.5.6\n"
+
+#: forum/feed.py:70 forum/models/page.py:5 forum/utils/pagination.py:162
+#: forum/views/readers.py:166 forum/views/readers.py:282
+#, fuzzy
+msgid "page"
+msgstr "страница"
+
+#: forum/feed.py:70 forum/utils/pagination.py:158 forum/views/readers.py:166
+msgid "pagesize"
+msgstr ""
+
+#: forum/feed.py:70 forum/utils/pagination.py:166 forum/views/readers.py:166
+msgid "sort"
+msgstr "подреди"
+
+#: forum/feed.py:86
+#, fuzzy, python-format
+msgid "Answers to: %s"
+msgstr "Отговори на %s"
+
+#: forum/feed.py:100
+#, fuzzy, python-format
+msgid "Answer by %s"
+msgstr "Отговори от %s"
+
+#: forum/feed.py:102
+#, python-format
+msgid "Comment by %(cauthor)s on %(pauthor)s's %(qora)s"
+msgstr "Коментар от %(cauthor)s на %(pauthor)s %(qora)s"
+
+#: forum/feed.py:103 forum/models/answer.py:5
+#: forum/skins/default/templates/osqaadmin/dashboard.html:24
+#: forum/skins/default/templates/osqaadmin/index.html:26
+#: forum/skins/default/templates/question_list/item.html:15
+#: forum/skins/zapprotect/templates/osqaadmin/dashboard.html:24
+#: forum/skins/zapprotect/templates/osqaadmin/index.html:26
+#: forum/skins/zapprotect/templates/question_list/item.html:15
+#: forum/views/writers.py:238 forum_modules/akismet/startup.py:59
+msgid "answer"
+msgstr "отговор"
+
+#: forum/feed.py:103 forum/models/question.py:19
+#: forum/skins/default/templates/osqaadmin/dashboard.html:19
+#: forum/skins/default/templates/osqaadmin/index.html:21
+#: forum/skins/zapprotect/templates/osqaadmin/dashboard.html:19
+#: forum/skins/zapprotect/templates/osqaadmin/index.html:21
+#: forum/views/writers.py:89 forum_modules/akismet/startup.py:58
+msgid "question"
+msgstr "въпрос"
+
+#: forum/registry.py:11 forum/registry.py:46
+#: forum/skins/default/templates/index.html:15
+#: forum/skins/default/templates/question_edit_tips.html:22
+#: forum/skins/zapprotect/templates/index.html:15
+#: forum/skins/zapprotect/templates/question_edit_tips.html:22
+msgid "faq"
+msgstr "чзв"
+
+#: forum/registry.py:12 forum/registry.py:47
+#: forum/skins/default/templates/index.html:14
+#: forum/skins/zapprotect/templates/index.html:14
+msgid "about"
+msgstr "за нас"
+
+#: forum/registry.py:15
+msgid "logout"
+msgstr "изход"
+
+#: forum/registry.py:15
+msgid "login"
+msgstr "вход"
+
+#: forum/registry.py:28
+msgid "administration"
+msgstr "администрация"
+
+#: forum/registry.py:41
+#, fuzzy
+msgid "contact"
+msgstr "съдържание"
+
+#: forum/registry.py:44
+#, fuzzy
+msgid "support"
+msgstr "плюс"
+
+#: forum/registry.py:45
+#, fuzzy
+msgid "privacy"
+msgstr "privacy"
+
+#: forum/registry.py:60 forum/skins/default/templates/users/edit.html:33
+#: forum/skins/zapprotect/templates/users/edit.html:33
+msgid "edit profile"
+msgstr "Редакция на профила"
+
+#: forum/registry.py:66
+#, fuzzy
+msgid "authentication settings"
+msgstr "Опции за оторизиране"
+
+#: forum/registry.py:72
+#, fuzzy
+msgid "email notification settings"
+msgstr "Опции за оторизиране"
+
+#: forum/registry.py:78
+msgid "other preferences"
+msgstr "други предпочитания"
+
+#: forum/registry.py:82
+msgid "Moderation tools"
+msgstr "Модераторски инструменти"
+
+#: forum/registry.py:84
+#, fuzzy
+msgid "withdraw suspension"
+msgstr "Изпратете Вашия отговор"
+
+#: forum/registry.py:84
+msgid "suspend this user"
+msgstr "спри този потребител"
+
+#: forum/registry.py:90
+msgid "give/take karma"
+msgstr "дай/вземи карма"
+
+#: forum/registry.py:97
+msgid "remove moderator status"
+msgstr "премахване на модераторски статут"
+
+#: forum/registry.py:97
+msgid "grant moderator status"
+msgstr "дай модераторски статут"
+
+#: forum/registry.py:103
+msgid "remove super user status"
+msgstr "премахване на супер потребителското състояние"
+
+#: forum/registry.py:103
+msgid "grant super user status"
+msgstr "предоставяне на статут супер потребител"
+
+#: forum/urls.py:34
+msgid "nimda/"
+msgstr ""
+
+#: forum/urls.py:43
+msgid "upfiles/"
+msgstr ""
+
+#: forum/urls.py:48
+msgid "faq/"
+msgstr ""
+
+#: forum/urls.py:48
+msgid "FAQ"
+msgstr ""
+
+#: forum/urls.py:50
+msgid "about/"
+msgstr ""
+
+#: forum/urls.py:51
+msgid "About"
+msgstr "За нас"
+
+#: forum/urls.py:52
+msgid "markdown_help/"
+msgstr ""
+
+#: forum/urls.py:55
+msgid "privacy/"
+msgstr ""
+
+#: forum/urls.py:56
+msgid "logout/"
+msgstr ""
+
+#: forum/urls.py:57
+msgid "answers/"
+msgstr ""
+
+#: forum/urls.py:57 forum/urls.py:69 forum/urls.py:126 forum/urls.py:200
+msgid "edit/"
+msgstr ""
+
+#: forum/urls.py:59
+msgid "revisions/"
+msgstr ""
+
+#: forum/urls.py:60 forum/urls.py:61 forum/urls.py:62 forum/urls.py:65
+#: forum/urls.py:66 forum/urls.py:69 forum/urls.py:71 forum/urls.py:73
+#: forum/urls.py:75 forum/urls.py:101 forum/urls.py:102 forum/urls.py:103
+msgid "questions/"
+msgstr ""
+
+#: forum/urls.py:61
+msgid "ask/"
+msgstr ""
+
+#: forum/urls.py:62
+#, fuzzy
+msgid "related_questions/"
+msgstr "Подобни въпроси"
+
+#: forum/urls.py:65
+msgid "unanswered/"
+msgstr ""
+
+#: forum/urls.py:71
+msgid "close/"
+msgstr ""
+
+#: forum/urls.py:73
+msgid "reopen/"
+msgstr ""
+
+#: forum/urls.py:75
+msgid "answer/"
+msgstr ""
+
+#: forum/urls.py:76
+msgid "pending-data/"
+msgstr ""
+
+#: forum/urls.py:78
+msgid "vote/"
+msgstr ""
+
+#: forum/urls.py:80
+#, fuzzy
+msgid "like_comment/"
+msgstr "answer comment"
+
+#: forum/urls.py:81
+#, fuzzy
+msgid "comment/"
+msgstr "post a comment"
+
+#: forum/urls.py:82
+#, fuzzy
+msgid "delete_comment/"
+msgstr "post a comment"
+
+#: forum/urls.py:84
+msgid "accept_answer/"
+msgstr ""
+
+#: forum/urls.py:86
+msgid "mark_favorite/"
+msgstr ""
+
+#: forum/urls.py:88
+msgid "flag/"
+msgstr ""
+
+#: forum/urls.py:89
+msgid "delete/"
+msgstr ""
+
+#: forum/urls.py:90 forum/urls.py:91
+msgid "subscribe/"
+msgstr ""
+
+#: forum/urls.py:92
+msgid "matching_tags/"
+msgstr ""
+
+#: forum/urls.py:93
+msgid "matching_users/"
+msgstr ""
+
+#: forum/urls.py:94
+msgid "node_markdown/"
+msgstr ""
+
+#: forum/urls.py:95
+#, fuzzy
+msgid "convert/"
+msgstr "съдържание"
+
+#: forum/urls.py:97
+msgid "wikify/"
+msgstr ""
+
+#: forum/urls.py:99
+msgid "question/"
+msgstr ""
+
+#: forum/urls.py:106 forum/urls.py:107
+msgid "tags/"
+msgstr ""
+
+#: forum/urls.py:109 forum/urls.py:113
+msgid "mark-tag/"
+msgstr ""
+
+#: forum/urls.py:109
+msgid "interesting/"
+msgstr ""
+
+#: forum/urls.py:113
+msgid "ignored/"
+msgstr ""
+
+#: forum/urls.py:117
+msgid "unmark-tag/"
+msgstr ""
+
+#: forum/urls.py:122 forum/urls.py:126 forum/urls.py:127 forum/urls.py:129
+#: forum/urls.py:131 forum/urls.py:133 forum/urls.py:135 forum/urls.py:137
+#: forum/urls.py:139 forum/urls.py:141 forum/urls.py:143 forum/urls.py:145
+msgid "users/"
+msgstr ""
+
+#: forum/urls.py:127
+#, fuzzy
+msgid "award/"
+msgstr "all badges"
+
+#: forum/urls.py:129
+#, fuzzy
+msgid "suspend/"
+msgstr "You can safely re-use the same login for all OpenID-enabled websites."
+
+#: forum/urls.py:131
+msgid "powers/"
+msgstr ""
+
+#: forum/urls.py:133
+msgid "subscriptions/"
+msgstr ""
+
+#: forum/urls.py:135
+msgid "preferences/"
+msgstr ""
+
+#: forum/urls.py:137
+msgid "favorites/"
+msgstr ""
+
+#: forum/urls.py:139
+#, fuzzy
+msgid "reputation/"
+msgstr "karma"
+
+#: forum/urls.py:141
+msgid "votes/"
+msgstr ""
+
+#: forum/urls.py:143
+msgid "recent/"
+msgstr ""
+
+#: forum/urls.py:146 forum/urls.py:147
+msgid "badges/"
+msgstr ""
+
+#: forum/urls.py:150
+msgid "upload/"
+msgstr ""
+
+#: forum/urls.py:151
+msgid "search/"
+msgstr ""
+
+#: forum/urls.py:152
+#, fuzzy
+msgid "contact/"
+msgstr "съдържание"
+
+#: forum/urls.py:156 forum/urls.py:157 forum/urls.py:158 forum/urls.py:160
+#: forum/urls.py:162 forum/urls.py:164 forum/urls.py:166 forum/urls.py:168
+#: forum/urls.py:170 forum/urls.py:172 forum/urls.py:174 forum/urls.py:176
+#: forum_modules/localauth/urls.py:7
+msgid "account/"
+msgstr ""
+
+#: forum/urls.py:156 forum/urls.py:158
+msgid "signin/"
+msgstr ""
+
+#: forum/urls.py:157
+msgid "signout/"
+msgstr ""
+
+#: forum/urls.py:160
+msgid "done/"
+msgstr ""
+
+#: forum/urls.py:162 forum_modules/localauth/urls.py:7
+msgid "register/"
+msgstr ""
+
+#: forum/urls.py:164
+msgid "validate/"
+msgstr ""
+
+#: forum/urls.py:166 forum/urls.py:168
+msgid "tempsignin/"
+msgstr ""
+
+#: forum/urls.py:170
+msgid "authsettings/"
+msgstr ""
+
+#: forum/urls.py:172 forum/urls.py:174
+msgid "providers/"
+msgstr ""
+
+#: forum/urls.py:172
+msgid "remove/"
+msgstr ""
+
+#: forum/urls.py:174
+msgid "add/"
+msgstr ""
+
+#: forum/urls.py:176
+msgid "send-validation/"
+msgstr ""
+
+#: forum/urls.py:179 forum/urls.py:180 forum/urls.py:182 forum/urls.py:183
+#: forum/urls.py:185 forum/urls.py:187 forum/urls.py:189 forum/urls.py:191
+#: forum/urls.py:193 forum/urls.py:195 forum/urls.py:198 forum/urls.py:200
+#: forum/urls.py:203 forum/urls.py:206 forum_modules/exporter/urls.py:8
+#: forum_modules/exporter/urls.py:9 forum_modules/exporter/urls.py:10
+#: forum_modules/exporter/urls.py:12 forum_modules/sximporter/urls.py:8
+msgid "admin/"
+msgstr ""
+
+#: forum/urls.py:180
+msgid "switch_interface/"
+msgstr ""
+
+#: forum/urls.py:182
+msgid "statistics/"
+msgstr ""
+
+#: forum/urls.py:183
+msgid "denormalize/"
+msgstr ""
+
+#: forum/urls.py:185
+msgid "go_bootstrap/"
+msgstr ""
+
+#: forum/urls.py:187
+msgid "go_defaults/"
+msgstr ""
+
+#: forum/urls.py:189 forum/urls.py:206
+#, fuzzy
+msgid "settings/"
+msgstr "karma"
+
+#: forum/urls.py:191
+msgid "maintenance/"
+msgstr ""
+
+#: forum/urls.py:193
+msgid "flagged_posts/"
+msgstr ""
+
+#: forum/urls.py:195 forum/urls.py:198 forum/urls.py:200
+msgid "static_pages/"
+msgstr ""
+
+#: forum/urls.py:198
+msgid "new/"
+msgstr ""
+
+#: forum/urls.py:203
+msgid "tools/"
+msgstr ""
+
+#: forum/actions/meta.py:39
+#, python-format
+msgid "%(user)s %(vote_desc)s %(post_desc)s"
+msgstr ""
+
+#: forum/actions/meta.py:58
+#, fuzzy
+msgid "voted up"
+msgstr "поддържан"
+
+#: forum/actions/meta.py:74
+msgid "voted down"
+msgstr "отхвърлен"
+
+#: forum/actions/meta.py:88
+#, fuzzy
+msgid "liked"
+msgstr "зададено"
+
+#: forum/actions/meta.py:116
+msgid "No reason given"
+msgstr "Без да изтъква причини"
+
+#: forum/actions/meta.py:121
+#, python-format
+msgid "%(user)s flagged %(post_desc)s: %(reason)s"
+msgstr ""
+
+#: forum/actions/meta.py:152 forum/actions/user.py:32
+#: forum/models/action.py:218
+msgid "your"
+msgstr "твой"
+
+#: forum/actions/meta.py:152 forum/actions/user.py:32
+msgid "his"
+msgstr "негов"
+
+#: forum/actions/meta.py:156
+#, python-format
+msgid ""
+"%(user)s accepted %(answerer)s answer on %(asker)s question %(question)s"
+msgstr ""
+
+#: forum/actions/meta.py:172
+#, python-format
+msgid "%(user)s marked %(post_desc)s as favorite"
+msgstr ""
+
+#: forum/actions/meta.py:192
+#, python-format
+msgid "%(user)s deleted %(post_desc)s"
+msgstr ""
+
+#: forum/actions/meta.py:201
+msgid "flagged by multiple users: "
+msgstr "отбелязан от няколко потребителя:"
+
+#: forum/actions/node.py:8
+msgid "Initial revision"
+msgstr "Първоначална версия"
+
+#: forum/actions/node.py:19 forum/templatetags/node_tags.py:203
+msgid "asked"
+msgstr "зададено"
+
+#: forum/actions/node.py:31
+#, fuzzy, python-format
+msgid "%(user)s asked %(question)s"
+msgstr "%(user)s попита %(question)s"
+
+#: forum/actions/node.py:37 forum/templatetags/node_tags.py:204
+msgid "answered"
+msgstr "отговорено"
+
+#: forum/actions/node.py:49
+#, fuzzy, python-format
+msgid "%(user)s answered %(asker)s on %(question)s"
+msgstr ""
+"<div class=\"questions-count\">%(num_q)s</div>questions <strong>without "
+"accepted answers</strong>"
+
+#: forum/actions/node.py:56
+#, fuzzy
+msgid "commented"
+msgstr "post a comment"
+
+#: forum/actions/node.py:64
+#, fuzzy, python-format
+msgid "%(user)s commented on %(post_desc)s"
+msgstr "Нов коментар на %(question_title)s"
+
+#: forum/actions/node.py:70 forum/actions/page.py:23
+#, fuzzy
+msgid "edited"
+msgstr "редактиран"
+
+#: forum/actions/node.py:82
+#, python-format
+msgid "%(user)s edited %(post_desc)s"
+msgstr "%(user)s редактира %(post_desc)s"
+
+#: forum/actions/node.py:91
+msgid "retagged"
+msgstr "претагнато"
+
+#: forum/actions/node.py:95
+msgid "Retag"
+msgstr "Нов таг"
+
+#: forum/actions/node.py:104
+#, python-format
+msgid "%(user)s retagged %(post_desc)s"
+msgstr "%(user)s ретагна %(post_desc)s"
+
+#: forum/actions/node.py:113
+#, fuzzy
+msgid "reverted"
+msgstr "претагнато"
+
+#: forum/actions/node.py:127
+#, python-format
+msgid ""
+"%(user)s reverted %(post_desc)s from revision %(initial)d (%(initial_sum)s) "
+"to revision %(final)d (%(final_sum)s)"
+msgstr ""
+"%(user)s върна %(post_desc)s от ревизия %(initial)d (%(initial_sum)s) до "
+"ревизия %(final)d (%(final_sum)s)"
+
+#: forum/actions/node.py:138
+#, fuzzy
+msgid "closed"
+msgstr "затворено"
+
+#: forum/actions/node.py:152
+#, python-format
+msgid "%(user)s closed %(post_desc)s: %(reason)s"
+msgstr "%(user)s затвори %(post_desc)s: %(reason)s"
+
+#: forum/actions/node.py:159
+#, fuzzy
+msgid "converted"
+msgstr "отхвърлен"
+
+#: forum/actions/node.py:177
+#, python-format
+msgid "%(user)s converted an answer to %(question)s into a comment"
+msgstr "%(user)s превърна отговора на %(question)s в коментар"
+
+#: forum/actions/node.py:183
+msgid "wikified"
+msgstr ""
+
+#: forum/actions/node.py:195
+#, python-format
+msgid "%(user)s marked %(node)s as community wiki."
+msgstr "%(user)s отбеляза %(node)s като част от уийки общност.\t"
+
+#: forum/actions/page.py:6
+#, fuzzy
+msgid "created"
+msgstr "създадено"
+
+#: forum/actions/page.py:17
+#, python-format
+msgid "%(user)s created a new page titled %(page)s"
+msgstr "%(user)s създаде нова страница озаглавена %(page)s"
+
+#: forum/actions/page.py:36
+#, python-format
+msgid "%(user)s edited the page titled %(page)s"
+msgstr "%(user)s редактира страницата озаглавена %(page)s"
+
+#: forum/actions/page.py:42
+msgid "published"
+msgstr "публикувано"
+
+#: forum/actions/page.py:55
+#, fuzzy, python-format
+msgid "%(user)s published a new page titled %(page)s"
+msgstr "%(username)s е нов потребител на %(app_name)s"
+
+#: forum/actions/user.py:10
+#, fuzzy
+msgid "joined"
+msgstr "игнорирано"
+
+#: forum/actions/user.py:20
+#, python-format
+msgid "%(user)s %(have_has)s joined the %(app_name)s Q&A community"
+msgstr "%(user)s %(have_has)s се присъедини към %(app_name)s Q&A общността"
+
+#: forum/actions/user.py:22
+msgid "have"
+msgstr "има"
+
+#: forum/actions/user.py:22
+msgid "has"
+msgstr "има"
+
+#: forum/actions/user.py:27
+#, fuzzy
+msgid "edited profile"
+msgstr "редактиран потребителски профил"
+
+#: forum/actions/user.py:30
+#, python-format
+msgid "%(user)s edited %(hes_or_your)s %(profile_link)s"
+msgstr "%(user)s редактира %(hes_or_your)s %(profile_link)s"
+
+#: forum/actions/user.py:33
+#, fuzzy
+msgid "profile"
+msgstr "профил"
+
+#: forum/actions/user.py:37
+msgid "gave bonus"
+msgstr "даде бонус"
+
+#: forum/actions/user.py:49
+#, python-format
+msgid "Congratulations, you have been awarded an extra %s reputation points."
+msgstr "Поздравления, вие сте наградени с допълнителни %s точки."
+
+#: forum/actions/user.py:50
+msgid "Thank you"
+msgstr "Благодаря"
+
+#: forum/actions/user.py:53
+#, python-format
+msgid "You have been penalized in %s reputation points."
+msgstr "Вие сте били санкционирани с %s точки."
+
+#: forum/actions/user.py:57 forum/templatetags/extra_tags.py:93
+#: forum_modules/exporter/templates/running.html:157
+msgid "unknown"
+msgstr "неизвестен"
+
+#: forum/actions/user.py:62
+#, python-format
+msgid ""
+"%(user)s awarded an extra %(value)s reputation points to %(users)s: %"
+"(message)s"
+msgstr "%(user)s награди с %(value)s точки  %(users)s: %(message)s\t"
+
+#: forum/actions/user.py:67
+#, python-format
+msgid ""
+"%(user)s penalised %(users)s in %(value)s reputation points: %(message)s"
+msgstr "%(user)s наказа %(users)s с %(value)s точки: %(message)s\t"
+
+#: forum/actions/user.py:75
+#, fuzzy
+msgid "was awarded"
+msgstr "всички награди"
+
+#: forum/actions/user.py:103
+#, python-format
+msgid ""
+"Congratulations, you have received a badge '%(badge_name)s'. Check out <a "
+"href=\"%(profile_url)s\">your profile</a>."
+msgstr ""
+"Честито! Получихте значка '%(badge_name)s'. Проверете във <a href=\"%"
+"(profile_url)s\">профила си</a>.\t"
+
+#: forum/actions/user.py:125
+#, python-format
+msgid "%(user)s %(were_was)s awarded the %(badge_name)s badge"
+msgstr "%(user)s  %(were_was)s спечели %(badge_name)s значка"
+
+#: forum/actions/user.py:127
+#, fuzzy
+msgid "were"
+msgstr "бяха"
+
+#: forum/actions/user.py:127
+msgid "was"
+msgstr "беше"
+
+#: forum/actions/user.py:132
+#, fuzzy
+msgid "suspended"
+msgstr "обновено"
+
+#: forum/actions/user.py:150
+msgid "Your suspension has been removed."
+msgstr "Вашата забрана беше отменена."
+
+#: forum/actions/user.py:154
+#, python-format
+msgid "for %s days"
+msgstr "за %s дена"
+
+#: forum/actions/user.py:156
+msgid "indefinetely"
+msgstr ""
+
+#: forum/actions/user.py:158
+#, python-format
+msgid "%(user)s suspended %(users)s %(suspension)s: %(msg)s"
+msgstr ""
+
+#: forum/actions/user.py:160 forum/views/users.py:241
+msgid "Bad behaviour"
+msgstr "Лошо поведение"
+
+#: forum/forms/admin.py:16
+#, fuzzy
+msgid "Please input at least one ip address"
+msgstr "въведете поне един IP адрес"
+
+#: forum/forms/admin.py:22
+#, python-format
+msgid "Invalid ip address: %s"
+msgstr "Невалиден IP адрес: %s"
+
+#: forum/forms/admin.py:25
+msgid "Please use the dotted quad notation for the ip addresses"
+msgstr ""
+
+#: forum/forms/admin.py:32
+msgid "Allow ips"
+msgstr ""
+
+#: forum/forms/admin.py:33
+msgid ""
+"Comma separated list of ips allowed to access the site while in maintenance"
+msgstr ""
+
+#: forum/forms/admin.py:37
+#: forum/skins/default/templates/users/karma_bonus.html:9
+#: forum/skins/zapprotect/templates/users/karma_bonus.html:9
+#, fuzzy
+msgid "Message"
+msgstr "Вашето съобщение:"
+
+#: forum/forms/admin.py:38
+msgid "A message to display to your site visitors while in maintainance mode"
+msgstr ""
+
+#: forum/forms/admin.py:43
+msgid "Default"
+msgstr ""
+
+#: forum/forms/admin.py:44
+msgid "Default with sidebar"
+msgstr ""
+
+#: forum/forms/admin.py:45
+#, fuzzy
+msgid "None"
+msgstr "бронз"
+
+#: forum/forms/admin.py:49 forum/settings/static.py:6
+#, fuzzy
+msgid "Markdown"
+msgstr "Markdown съвети"
+
+#: forum/forms/admin.py:50 forum/settings/static.py:7
+msgid "HTML"
+msgstr ""
+
+#: forum/forms/admin.py:51 forum/settings/static.py:8
+msgid "Escaped"
+msgstr ""
+
+#: forum/forms/admin.py:76
+#: forum/skins/default/templates/osqaadmin/nodeman.html:284
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:284
+#, fuzzy
+msgid "Title"
+msgstr "заглавие"
+
+#: forum/forms/admin.py:78
+msgid "Page URL"
+msgstr "URL адрес на страницата"
+
+#: forum/forms/admin.py:80
+#, fuzzy
+msgid "Page Content"
+msgstr "съдържание"
+
+#: forum/forms/admin.py:81
+msgid "Mime Type"
+msgstr "Mime Тип"
+
+#: forum/forms/admin.py:84
+msgid "Render Mode"
+msgstr "Render Mode"
+
+#: forum/forms/admin.py:87
+msgid "Template"
+msgstr "Шаблон"
+
+#: forum/forms/admin.py:88
+msgid "Sidebar Content"
+msgstr ""
+
+#: forum/forms/admin.py:89
+msgid "Wrap sidebar block"
+msgstr ""
+
+#: forum/forms/admin.py:91
+msgid "Sidebar Render Mode"
+msgstr ""
+
+#: forum/forms/admin.py:93
+#, fuzzy
+msgid "Allow comments"
+msgstr "post a comment"
+
+#: forum/forms/admin.py:100
+#, fuzzy
+msgid "send validation email"
+msgstr "Stop Email"
+
+#: forum/forms/admin.py:105
+#, fuzzy
+msgid "email address"
+msgstr "Имейл адрес (не го споделяме)"
+
+#: forum/forms/auth.py:21
+#, fuzzy
+msgid "Your account email"
+msgstr ""
+"<strong>Нов имейл:</strong> (няма да бъде споделян, трябва да бъде "
+"действителен)"
+
+#: forum/forms/auth.py:23
+msgid "You cannot leave this field blank"
+msgstr "Трябва да въведете нещо"
+
+#: forum/forms/auth.py:24 forum/forms/general.py:103
+msgid "please enter a valid email address"
+msgstr "въведете действителен имейл адрес"
+
+#: forum/forms/auth.py:32
+msgid "Sorry, but this email is not on our database."
+msgstr "За съжаление този имейл не е в нашата база данни."
+
+#: forum/forms/auth.py:40
+msgid "okay, let's try!"
+msgstr "добре, ще опитам"
+
+#: forum/forms/auth.py:41
+msgid "no OSQA community email please, thanks"
+msgstr "не искам имейли от Zapprotect"
+
+#: forum/forms/auth.py:44
+msgid "please choose one of the options above"
+msgstr "изберете някоя от следните опции"
+
+#: forum/forms/auth.py:51
+msgid "Current password"
+msgstr "Текуща парола"
+
+#: forum/forms/auth.py:62
+msgid ""
+"Old password is incorrect.                     Please enter the correct "
+"password."
+msgstr "Текущата парола не е вярна. Моля, въведете истинската парола."
+
+#: forum/forms/general.py:27
+msgid "this field is required"
+msgstr "Това поле е задължително"
+
+#: forum/forms/general.py:40
+msgid "choose a username"
+msgstr "Изберете потребителско име"
+
+#: forum/forms/general.py:45
+msgid "user name is required"
+msgstr "потребителско име е необходимо"
+
+#: forum/forms/general.py:46
+msgid "sorry, this name is taken, please choose another"
+msgstr "За съжаление, това име е взето, моля изберете друго"
+
+#: forum/forms/general.py:47
+msgid "sorry, this name is not allowed, please choose another"
+msgstr "За съжаление, това име не е позволено, моля изберете друго"
+
+#: forum/forms/general.py:48
+msgid "sorry, there is no user with this name"
+msgstr "За съжаление, няма потребител с това име"
+
+#: forum/forms/general.py:49
+msgid "sorry, we have a serious error - user name is taken by several users"
+msgstr ""
+"За съжаление, ние имаме една сериозна грешка - потребителско име се взема от "
+"няколко потребители"
+
+#: forum/forms/general.py:50
+msgid "user name can only consist of letters, empty space and underscore"
+msgstr ""
+"потребителското име може да се състои само от букви, празно място и "
+"подчертаване"
+
+#: forum/forms/general.py:51
+#, python-format
+msgid "user name is to short, please use at least %d characters"
+msgstr "потребителското име е прекалено кратко, използвайте поне %d символа"
+
+#: forum/forms/general.py:101
+msgid "your email address"
+msgstr "Вашия имейл <i>(не се споделя)</i>"
+
+#: forum/forms/general.py:102
+msgid "email address is required"
+msgstr "имейл адреса се изисква"
+
+#: forum/forms/general.py:104
+msgid "this email is already used by someone else, please choose another"
+msgstr "този имейл вече се използва от някой друг, моля изберете друг"
+
+#: forum/forms/general.py:129
+msgid "choose password"
+msgstr "Изберете парола"
+
+#: forum/forms/general.py:130
+msgid "password is required"
+msgstr "Изисква се парола"
+
+#: forum/forms/general.py:133
+msgid "retype password"
+msgstr "Парола <i>(напишете отново)</i>"
+
+#: forum/forms/general.py:134
+msgid "please, retype your password"
+msgstr "Моля, въведете отново паролата си"
+
+#: forum/forms/general.py:135
+msgid "sorry, entered passwords did not match, please try again"
+msgstr "Съжаляваме, вписаните пароли не съвпадат, опитайте отново"
+
+#: forum/forms/qanda.py:19
+#: forum/skins/default/templates/sidebar/markdown_help.html:12
+#: forum/skins/default/templates/sidebar/markdown_help.html:17
+#: forum/skins/zapprotect/templates/sidebar/markdown_help.html:12
+#: forum/skins/zapprotect/templates/sidebar/markdown_help.html:17
+msgid "title"
+msgstr "заглавие"
+
+#: forum/forms/qanda.py:20
+msgid "please enter a descriptive title for your question"
+msgstr "въведете описателно заглавие на въпроса"
+
+#: forum/forms/qanda.py:25
+#, fuzzy, python-format
+msgid "title must be must be at least %s characters"
+msgstr "заглавието трябва да бъде > 10 символа"
+
+#: forum/forms/qanda.py:33
+msgid "content"
+msgstr "съдържание"
+
+#: forum/forms/qanda.py:46
+#, fuzzy, python-format
+msgid "question content must be at least %s characters"
+msgstr "съдържанието на въпроса трябва да бъде > 10 символа"
+
+#: forum/forms/qanda.py:57
+#, fuzzy, python-format
+msgid "answer content must be at least %s characters"
+msgstr "съдържанието на въпроса трябва да бъде > 10 символа"
+
+#: forum/forms/qanda.py:68 forum/skins/default/templates/header.html:35
+#: forum/skins/default/templates/search.html:20
+#: forum/skins/zapprotect/templates/header.html:35
+#: forum/skins/zapprotect/templates/search.html:20 forum/views/readers.py:218
+msgid "tags"
+msgstr "тагове"
+
+#: forum/forms/qanda.py:70
+#, fuzzy, python-format
+msgid ""
+"Tags are short keywords, with no spaces within. At least %(min)s and up to %"
+"(max)s tags can be used."
+msgstr ""
+"Таговете са кратки ключови думи, без разстояние между тях. Можете да "
+"използвате до 5 тага."
+
+#: forum/forms/qanda.py:86
+#, python-format
+msgid "please use between %(min)s and %(max)s tags"
+msgstr "моля използвайте от %(min)s до %(max)s тага"
+
+#: forum/forms/qanda.py:92
+#, python-format
+msgid "please use between %(min)s and %(max)s characters in you tags"
+msgstr "използвайте от %(min)s до %(max)s символа в таговете"
+
+#: forum/forms/qanda.py:94
+#, fuzzy
+msgid ""
+"please use following characters in tags: letters , numbers, and characters "
+"'.-_'"
+msgstr "за таговете използвайте символите a-z, а-я, числа, знаци и '.-_#'"
+
+#: forum/forms/qanda.py:104
+#, python-format
+msgid ""
+"You don't have enough reputation to create new tags. The following tags do "
+"not exist yet: %s"
+msgstr ""
+"Вие не разполагат с достатъчно репутация, за да създавате нови тагове. "
+"Следните бележки не съществуват още: %s"
+
+#: forum/forms/qanda.py:114
+#: forum/skins/default/templates/question_summary_list_roll.html:26
+#: forum/skins/default/templates/question_summary_list_roll.html:38
+#: forum/skins/zapprotect/templates/question_summary_list_roll.html:26
+#: forum/skins/zapprotect/templates/question_summary_list_roll.html:38
+msgid "community wiki"
+msgstr "уики общност"
+
+#: forum/forms/qanda.py:115
+msgid ""
+"if you choose community wiki option, the question and answer do not generate "
+"points and name of author will not be shown"
+msgstr ""
+"ако изберете уики общност, въпроса и отговора не генерират точки и името на "
+"автора няма да бъде показвано"
+
+#: forum/forms/qanda.py:133
+msgid "update summary:"
+msgstr "основна информация за обновяването:"
+
+#: forum/forms/qanda.py:134
+msgid ""
+"enter a brief summary of your revision (e.g. fixed spelling, grammar, "
+"improved style, this field is optional)"
+msgstr ""
+"въведете кратко заключение на новата ревизия (редактиран правопис, "
+"граматика, подобрен стил, това поле не е задължително)"
+
+#: forum/forms/qanda.py:138
+msgid "Your message:"
+msgstr "Вашето съобщение:"
+
+#: forum/forms/qanda.py:144
+msgid "Your name:"
+msgstr "Вашето име:"
+
+#: forum/forms/qanda.py:145
+msgid "Email (not shared with anyone):"
+msgstr "Имейл (не се споделя с никой):"
+
+#: forum/forms/qanda.py:236
+msgid "this email does not have to be linked to gravatar"
+msgstr "този имейл не е нужно да бъде свързан с gravatar"
+
+#: forum/forms/qanda.py:237
+msgid "Real name"
+msgstr "Истинско име"
+
+#: forum/forms/qanda.py:238
+msgid "Website"
+msgstr "Уеб сайт"
+
+#: forum/forms/qanda.py:239
+msgid "Location"
+msgstr "Местоположение"
+
+#: forum/forms/qanda.py:240
+msgid "Date of birth"
+msgstr "Дата на раждане"
+
+#: forum/forms/qanda.py:240
+msgid "will not be shown, used to calculate age, format: YYYY-MM-DD"
+msgstr ""
+"няма да бъде показвано, използва се за изчисляване на възрастта, формат: "
+"YYYY-MM-DD"
+
+#: forum/forms/qanda.py:241
+#: forum/skins/default/templates/account_settings.html:21
+#: forum/skins/default/templates/osqaadmin/moderation.html:68
+#: forum/skins/zapprotect/templates/account_settings.html:21
+#: forum/skins/zapprotect/templates/osqaadmin/moderation.html:68
+msgid "Profile"
+msgstr "Профил"
+
+#: forum/forms/qanda.py:246
+msgid "Screen name"
+msgstr "Публично име"
+
+#: forum/forms/qanda.py:273
+msgid "this email has already been registered, please use another one"
+msgstr "този имейл вече е използван, моля, въведете друг"
+
+#: forum/forms/qanda.py:278
+msgid "Instantly"
+msgstr "Моментално"
+
+#: forum/forms/qanda.py:281
+msgid "No notifications"
+msgstr "Без известия"
+
+#: forum/middleware/anon_user.py:34
+#, python-format
+msgid "First time here? Check out the <a href=\"%s\">FAQ</a>!"
+msgstr "За първи път тук? Проверете <a href=\"%s\">ЧЗП</a>."
+
+#: forum/models/action.py:215
+msgid "You"
+msgstr "Вие"
+
+#: forum/models/action.py:230
+#, fuzzy, python-format
+msgid "on %(link)s"
+msgstr "в %(link)s"
+
+#: forum/models/action.py:234
+#, python-format
+msgid "%(user)s %(node_name)s %(node_desc)s"
+msgstr ""
+
+#: forum/models/comment.py:6 forum/views/commands.py:230
+#: forum/views/commands.py:256 forum_modules/akismet/startup.py:60
+#, fuzzy
+msgid "comment"
+msgstr "коментирай"
+
+#: forum/models/meta.py:63
+msgid "Unknown"
+msgstr "Неизвестен"
+
+#: forum/models/meta.py:68
+msgid "No description available"
+msgstr "Няма описание"
+
+#: forum/models/node.py:237
+#, fuzzy
+msgid "post"
+msgstr "добавено"
+
+#: forum/models/page.py:31
+#, python-format
+msgid "[Unpublished] %s"
+msgstr "[Непубликувани] %s"
+
+#: forum/models/question.py:33
+msgid "[deleted] "
+msgstr "[изтрит]"
+
+#: forum/models/question.py:36
+msgid "[closed] "
+msgstr "[затворен]"
+
+#: forum/models/tag.py:38
+msgid "interesting"
+msgstr "интересно"
+
+#: forum/models/tag.py:38
+msgid "ignored"
+msgstr "игнорирано"
+
+#: forum/models/user.py:201 forum/views/readers.py:115
+#, fuzzy
+msgid "asked-by"
+msgstr "зададено"
+
+#: forum/models/user.py:205 forum/views/readers.py:118
+#, fuzzy
+msgid "answered-by"
+msgstr "отговорено"
+
+#: forum/models/user.py:209 forum/views/readers.py:121
+#, fuzzy
+msgid "subscribed-by"
+msgstr "абонирай ме"
+
+#: forum/settings/__init__.py:44
+msgid "Badges config"
+msgstr "Настройка на значките"
+
+#: forum/settings/__init__.py:44
+msgid "Configure badges on your OSQA site."
+msgstr ""
+
+#: forum/settings/accept.py:5
+#, fuzzy
+msgid "Accepting answers"
+msgstr "oldest"
+
+#: forum/settings/accept.py:5
+msgid "Settings to tweak the behaviour of accepting answers."
+msgstr ""
+
+#: forum/settings/accept.py:8
+#, fuzzy
+msgid "Disallow answers to be accepted"
+msgstr "answer accepted"
+
+#: forum/settings/accept.py:9
+msgid ""
+"Disable accepting answers feature. If you reenable it in the future, "
+"currently accepted answers will still be marked as accepted."
+msgstr ""
+
+#: forum/settings/accept.py:13
+#, fuzzy
+msgid "Maximum accepted answers per question"
+msgstr "не е отговор на въпроса"
+
+#: forum/settings/accept.py:14
+msgid "How many accepted answers are allowed per question. Use 0 for no limit."
+msgstr ""
+
+#: forum/settings/accept.py:17
+msgid "Maximum accepted answers per user/question"
+msgstr ""
+
+#: forum/settings/accept.py:18
+msgid ""
+"If more than one accpeted answer is allowed, how many can be accepted per "
+"single user per question."
+msgstr ""
+
+#: forum/settings/accept.py:21
+#, fuzzy
+msgid "Users an accept own answer"
+msgstr "oldest"
+
+#: forum/settings/accept.py:22
+msgid "Are normal users allowed to accept theyr own answers.."
+msgstr ""
+"Дали обикновените потребители могат да се приемат собствените си отговори"
+
+#: forum/settings/basic.py:9
+#: forum/skins/default/templates/osqaadmin/djstyle_base.html:67
+#: forum/skins/zapprotect/templates/osqaadmin/djstyle_base.html:67
+#, fuzzy
+msgid "Basic settings"
+msgstr ""
+"<span class='big strong'>Adjust frequency of email updates.</span> Receive "
+"updates on interesting questions by email, <strong><br/>help the community</"
+"strong> by answering questions of your colleagues. If you do not wish to "
+"receive emails - select 'no email' on all items below.<br/>Updates are only "
+"sent when there is any new activity on selected items."
+
+#: forum/settings/basic.py:9
+msgid "The basic settings for your application"
+msgstr "Основните настройки за вашето приложение"
+
+#: forum/settings/basic.py:12
+msgid "Application logo"
+msgstr "Лого"
+
+#: forum/settings/basic.py:13
+#, fuzzy
+msgid "Your site main logo."
+msgstr ""
+"<strong>Your new Email:</strong> (will <strong>not</strong> be shown to "
+"anyone, must be valid)"
+
+#: forum/settings/basic.py:17
+msgid "Favicon"
+msgstr ""
+
+#: forum/settings/basic.py:18
+msgid "Your site favicon."
+msgstr ""
+
+#: forum/settings/basic.py:22
+msgid "Application title"
+msgstr ""
+
+#: forum/settings/basic.py:23
+msgid "The title of your application that will show in the browsers title bar"
+msgstr ""
+
+#: forum/settings/basic.py:26
+msgid "Application short name"
+msgstr ""
+
+#: forum/settings/basic.py:30
+msgid "Application keywords"
+msgstr ""
+
+#: forum/settings/basic.py:31
+msgid "The meta keywords that will be available through the HTML meta tags."
+msgstr ""
+
+#: forum/settings/basic.py:34
+#, fuzzy
+msgid "Application description"
+msgstr ""
+"Gold badge is the highest award in this community. To obtain it have to show "
+"profound knowledge and ability in addition to your active participation."
+
+#: forum/settings/basic.py:35
+msgid "The description of your application"
+msgstr ""
+
+#: forum/settings/basic.py:39
+msgid "Copyright notice"
+msgstr ""
+
+#: forum/settings/basic.py:40
+msgid "The copyright notice visible at the footer of your page."
+msgstr ""
+
+#: forum/settings/basic.py:43
+msgid "Support URL"
+msgstr ""
+
+#: forum/settings/basic.py:44
+msgid ""
+"The URL provided for users to get support. It can be http: or mailto: or "
+"whatever your preferred support scheme is."
+msgstr ""
+
+#: forum/settings/basic.py:48
+msgid "Contact URL"
+msgstr ""
+
+#: forum/settings/basic.py:49
+msgid ""
+"The URL provided for users to contact you. It can be http: or mailto: or "
+"whatever your preferred contact scheme is."
+msgstr ""
+
+#: forum/settings/email.py:5
+msgid "Email settings"
+msgstr ""
+
+#: forum/settings/email.py:5
+msgid "Email server and other email related settings."
+msgstr ""
+
+#: forum/settings/email.py:8
+msgid "Email Server"
+msgstr ""
+
+#: forum/settings/email.py:9
+msgid "The SMTP server through which your application will be sending emails."
+msgstr ""
+
+#: forum/settings/email.py:13
+msgid "Email Port"
+msgstr ""
+
+#: forum/settings/email.py:14
+msgid ""
+"The port on which your SMTP server is listening to. Usually this is 25, but "
+"can be something else."
+msgstr ""
+
+#: forum/settings/email.py:18
+msgid "Email User"
+msgstr ""
+
+#: forum/settings/email.py:19
+msgid "The username for your SMTP connection."
+msgstr ""
+
+#: forum/settings/email.py:23
+msgid "Email Password"
+msgstr ""
+
+#: forum/settings/email.py:24
+msgid "The password for your SMTP connection."
+msgstr ""
+
+#: forum/settings/email.py:29
+msgid "Use TLS"
+msgstr ""
+
+#: forum/settings/email.py:30
+msgid "Does your SMTP server usFes TLS for authentication."
+msgstr ""
+
+#: forum/settings/email.py:34
+#, fuzzy
+msgid "Site 'from' email address"
+msgstr "Your email <i>(never shared)</i>"
+
+#: forum/settings/email.py:35
+msgid ""
+"The address that will show up on the 'from' field on emails sent by your "
+"website."
+msgstr ""
+
+#: forum/settings/email.py:39
+#, fuzzy
+msgid "Email subject prefix"
+msgstr "Welcome to the Q&A forum"
+
+#: forum/settings/email.py:40
+msgid ""
+"Every email sent through your website will have the subject prefixed by this "
+"string. It's usually a good idea to have such a prefix so your users can "
+"easilly set up a filter on theyr email clients."
+msgstr ""
+
+#: forum/settings/email.py:44
+msgid "Email Footer Text"
+msgstr ""
+
+#: forum/settings/email.py:45
+msgid ""
+"Email footer text, usually \"CAN SPAM\" compliance, or the physical address "
+"of the organization running the website. See <a href=\"http://en.wikipedia."
+"org/wiki/CAN-SPAM_Act_of_2003\">this Wikipedia article</a> for more info."
+msgstr ""
+
+#: forum/settings/email.py:49
+msgid "Email Border color"
+msgstr ""
+
+#: forum/settings/email.py:50
+msgid "The outter border color of the email base template"
+msgstr ""
+
+#: forum/settings/email.py:54
+msgid "Email Paragraph style"
+msgstr ""
+
+#: forum/settings/email.py:55
+msgid "A valid css string to be used to style email paragraphs (the P tag)."
+msgstr ""
+
+#: forum/settings/email.py:59
+msgid "Email link style"
+msgstr ""
+
+#: forum/settings/email.py:60
+msgid "A valid css string to be used to style email links (the A tag)."
+msgstr ""
+
+#: forum/settings/extkeys.py:4
+msgid "External Keys"
+msgstr ""
+
+#: forum/settings/extkeys.py:4
+msgid ""
+"Keys for various external providers that your application may optionally use."
+msgstr ""
+
+#: forum/settings/extkeys.py:7
+msgid "Google sitemap code"
+msgstr ""
+
+#: forum/settings/extkeys.py:8
+msgid ""
+"This is the code you get when you register your site at <a href='https://www."
+"google.com/webmasters/tools/'>Google webmaster central</a>."
+msgstr ""
+
+#: forum/settings/extkeys.py:12
+msgid "Google analytics key"
+msgstr ""
+
+#: forum/settings/extkeys.py:13
+msgid ""
+"Your Google analytics key. You can get one at the <a href='http://www.google."
+"com/analytics/'>Google analytics official website</a>"
+msgstr ""
+
+#: forum/settings/form.py:5
+msgid "Form settings"
+msgstr ""
+
+#: forum/settings/form.py:5
+#, fuzzy
+msgid "General settings for the OSQA forms."
+msgstr "Поздрави от Zapprotect Q&A"
+
+#: forum/settings/form.py:8
+#, fuzzy
+msgid "Enable community wiki"
+msgstr "уики общност"
+
+#: forum/settings/form.py:9
+msgid "Can questions or answers be marked as community wiki."
+msgstr ""
+
+#: forum/settings/form.py:13
+#, fuzzy
+msgid "Limit tag creation"
+msgstr "karma"
+
+#: forum/settings/form.py:14
+msgid ""
+"Limit tag creation to super users, staff or users with a minimum reputation."
+msgstr ""
+
+#: forum/settings/form.py:20
+msgid "Minimum number of characters for a question's title"
+msgstr ""
+
+#: forum/settings/form.py:21
+msgid ""
+"The minimum number of characters a user must enter into the title field of a "
+"question."
+msgstr ""
+
+#: forum/settings/form.py:28
+msgid "Minimum number of characters for a question's content"
+msgstr ""
+
+#: forum/settings/form.py:29
+msgid ""
+"The minimum number of characters a user must enter into the content field of "
+"a question."
+msgstr ""
+
+#: forum/settings/form.py:36
+#, fuzzy
+msgid "Empty question content"
+msgstr "коментар на въпроса"
+
+#: forum/settings/form.py:37
+msgid "If a question's content can be empty."
+msgstr ""
+
+#: forum/settings/form.py:45
+msgid "Required number of tags per question"
+msgstr ""
+
+#: forum/settings/form.py:46
+msgid "How many tags are required in questions."
+msgstr ""
+
+#: forum/settings/form.py:50
+msgid "Maximum number of tags per question"
+msgstr ""
+
+#: forum/settings/form.py:51
+msgid "How many tags are allowed in questions."
+msgstr ""
+
+#: forum/settings/form.py:55
+msgid "Minimum length of a tag"
+msgstr ""
+
+#: forum/settings/form.py:56
+msgid "How short a tag can be."
+msgstr ""
+
+#: forum/settings/form.py:60
+msgid "Maximum length of a tag"
+msgstr ""
+
+#: forum/settings/form.py:61
+msgid "How long a tag can be."
+msgstr ""
+
+#: forum/settings/form.py:69
+msgid "Minimum number of characters for a comment"
+msgstr ""
+
+#: forum/settings/form.py:70
+msgid ""
+"The minimum number of characters a user must enter into the body of a "
+"comment."
+msgstr ""
+
+#: forum/settings/form.py:73
+msgid "Maximum length of comment"
+msgstr ""
+
+#: forum/settings/form.py:74
+msgid ""
+"The maximum number of characters a user can enter into the body of a comment."
+msgstr ""
+
+#: forum/settings/form.py:77
+msgid "Allow markdown in comments"
+msgstr ""
+
+#: forum/settings/form.py:78
+msgid "Allow users to use markdown in comments."
+msgstr ""
+
+#: forum/settings/form.py:82
+msgid "Show author gravatar in comments"
+msgstr ""
+
+#: forum/settings/form.py:83
+msgid "Show the gravatar image of a comment author."
+msgstr ""
+
+#: forum/settings/forms.py:52
+#, fuzzy
+msgid "context"
+msgstr "съдържание"
+
+#: forum/settings/forms.py:52
+msgid "default"
+msgstr ""
+
+#: forum/settings/forms.py:65
+#, fuzzy
+msgid "Change this:"
+msgstr "Change Email"
+
+#: forum/settings/minrep.py:4
+#, fuzzy
+msgid "Minimum reputation config"
+msgstr "karma"
+
+#: forum/settings/minrep.py:4
+msgid ""
+"Configure the minimum reputation required to perform certain actions on your "
+"site."
+msgstr ""
+
+#: forum/settings/minrep.py:7
+msgid "Minimum reputation to vote up"
+msgstr ""
+
+#: forum/settings/minrep.py:8
+msgid "The minimum reputation an user must have to be allowed to vote up."
+msgstr ""
+
+#: forum/settings/minrep.py:11
+#, fuzzy
+msgid "Minimum reputation to vote down"
+msgstr "user karma"
+
+#: forum/settings/minrep.py:12
+msgid "The minimum reputation an user must have to be allowed to vote down."
+msgstr ""
+
+#: forum/settings/minrep.py:15
+msgid "Minimum reputation to flag a post"
+msgstr ""
+
+#: forum/settings/minrep.py:16
+msgid "The minimum reputation an user must have to be allowed to flag a post."
+msgstr ""
+
+#: forum/settings/minrep.py:19
+#, fuzzy
+msgid "Minimum reputation to comment"
+msgstr "user karma"
+
+#: forum/settings/minrep.py:20
+msgid ""
+"The minimum reputation an user must have to be allowed to comment a post."
+msgstr ""
+
+#: forum/settings/minrep.py:23
+#, fuzzy
+msgid "Minimum reputation to like a comment"
+msgstr "user karma"
+
+#: forum/settings/minrep.py:24
+msgid ""
+"The minimum reputation an user must have to be allowed to \"like\" a comment."
+msgstr ""
+
+#: forum/settings/minrep.py:27
+msgid "Minimum reputation to upload"
+msgstr ""
+
+#: forum/settings/minrep.py:28
+msgid ""
+"The minimum reputation an user must have to be allowed to upload a file."
+msgstr ""
+
+#: forum/settings/minrep.py:31
+#, fuzzy
+msgid "Minimum reputation to create tags"
+msgstr "user karma"
+
+#: forum/settings/minrep.py:32
+msgid ""
+"The minimum reputation an user must have to be allowed to create new tags."
+msgstr ""
+
+#: forum/settings/minrep.py:35
+msgid "Minimum reputation to close own question"
+msgstr ""
+
+#: forum/settings/minrep.py:36
+msgid ""
+"The minimum reputation an user must have to be allowed to close his own "
+"question."
+msgstr ""
+
+#: forum/settings/minrep.py:39
+msgid "Minimum reputation to reopen own question"
+msgstr ""
+
+#: forum/settings/minrep.py:40
+msgid ""
+"The minimum reputation an user must have to be allowed to reopen his own "
+"question."
+msgstr ""
+
+#: forum/settings/minrep.py:43
+msgid "Minimum reputation to retag others questions"
+msgstr ""
+
+#: forum/settings/minrep.py:44
+msgid ""
+"The minimum reputation an user must have to be allowed to retag others "
+"questions."
+msgstr ""
+
+#: forum/settings/minrep.py:47
+msgid "Minimum reputation to edit wiki posts"
+msgstr ""
+
+#: forum/settings/minrep.py:48
+msgid ""
+"The minimum reputation an user must have to be allowed to edit community "
+"wiki posts."
+msgstr ""
+
+#: forum/settings/minrep.py:51
+#, fuzzy
+msgid "Minimum reputation to mark post as community wiki"
+msgstr "user karma"
+
+#: forum/settings/minrep.py:52
+msgid ""
+"The minimum reputation an user must have to be allowed to mark a post as "
+"community wiki."
+msgstr ""
+
+#: forum/settings/minrep.py:55
+msgid "Minimum reputation to edit others posts"
+msgstr ""
+
+#: forum/settings/minrep.py:56
+msgid ""
+"The minimum reputation an user must have to be allowed to edit others posts."
+msgstr ""
+
+#: forum/settings/minrep.py:59
+msgid "Minimum reputation to close others posts"
+msgstr ""
+
+#: forum/settings/minrep.py:60
+msgid ""
+"The minimum reputation an user must have to be allowed to close others posts."
+msgstr ""
+
+#: forum/settings/minrep.py:63
+#, fuzzy
+msgid "Minimum reputation to delete comments"
+msgstr "user karma"
+
+#: forum/settings/minrep.py:64
+msgid ""
+"The minimum reputation an user must have to be allowed to delete comments."
+msgstr ""
+
+#: forum/settings/minrep.py:67
+#, fuzzy
+msgid "Minimum reputation to convert answers to comment"
+msgstr "user karma"
+
+#: forum/settings/minrep.py:68
+msgid ""
+"The minimum reputation an user must have to be allowed to convert an answer "
+"into a comment."
+msgstr ""
+
+#: forum/settings/minrep.py:71
+msgid "Minimum reputation to view offensive flags"
+msgstr ""
+
+#: forum/settings/minrep.py:72
+msgid "The minimum reputation an user must have to view offensive flags."
+msgstr ""
+
+#: forum/settings/moderation.py:7
+#, fuzzy
+msgid "Moderation settings"
+msgstr "Опции за оторизиране"
+
+#: forum/settings/moderation.py:7
+msgid "Define the moderation workflow of your site"
+msgstr ""
+
+#: forum/settings/moderation.py:13
+msgid "Flag Reasons"
+msgstr ""
+
+#: forum/settings/moderation.py:14
+msgid "Create some flag reasons to use in the flag post popup."
+msgstr ""
+
+#: forum/settings/moderation.py:22
+msgid "Close Reasons"
+msgstr ""
+
+#: forum/settings/moderation.py:23
+msgid "Create some close reasons to use in the close question popup."
+msgstr ""
+
+#: forum/settings/repgain.py:4
+msgid "Reputation gains and losses config"
+msgstr ""
+
+#: forum/settings/repgain.py:4
+msgid ""
+"Configure the reputation points a user may gain or lose upon certain actions."
+msgstr ""
+
+#: forum/settings/repgain.py:7
+#, fuzzy
+msgid "Initial reputation"
+msgstr "karma"
+
+#: forum/settings/repgain.py:8
+msgid "The initial reputation an user gets when he first signs in."
+msgstr ""
+
+#: forum/settings/repgain.py:12
+msgid "Maximum reputation a user can gain in one day for being upvoted."
+msgstr ""
+
+#: forum/settings/repgain.py:15
+msgid "Rep gain by upvoted"
+msgstr ""
+
+#: forum/settings/repgain.py:16
+msgid "Reputation a user gains for having one of his posts up voted."
+msgstr ""
+
+#: forum/settings/repgain.py:19
+msgid "Rep lost by downvoted"
+msgstr ""
+
+#: forum/settings/repgain.py:20
+msgid "Reputation a user loses for having one of his posts down voted."
+msgstr ""
+
+#: forum/settings/repgain.py:23
+msgid "Rep lost by downvoting"
+msgstr ""
+
+#: forum/settings/repgain.py:24
+msgid "Reputation a user loses for down voting a post."
+msgstr ""
+
+#: forum/settings/repgain.py:28
+msgid "Rep gain by accepted answer"
+msgstr ""
+
+#: forum/settings/repgain.py:29
+msgid "Reputation a user gains for having one of his answers accepted."
+msgstr ""
+
+#: forum/settings/repgain.py:32
+msgid "Rep gain by accepting answer"
+msgstr ""
+
+#: forum/settings/repgain.py:33
+msgid ""
+"Reputation a user gains for accepting an answer to one of his questions."
+msgstr ""
+
+#: forum/settings/repgain.py:36
+msgid "Rep lost by post flagged"
+msgstr ""
+
+#: forum/settings/repgain.py:37
+msgid "Reputation a user loses by having one of his posts flagged."
+msgstr ""
+
+#: forum/settings/repgain.py:40
+msgid "Rep lost by post flagged and hidden"
+msgstr ""
+
+#: forum/settings/repgain.py:41
+msgid ""
+"Reputation a user loses by having the last revision of one of his posts "
+"flagged the enough number of times to hide the post."
+msgstr ""
+
+#: forum/settings/repgain.py:44
+msgid "Rep lost by post flagged and deleted"
+msgstr ""
+
+#: forum/settings/repgain.py:45
+msgid ""
+"Reputation a user loses by having the last revision of one of his posts "
+"flagged the enough number of times to delete the post."
+msgstr ""
+
+#: forum/settings/sidebar.py:10
+msgid "Show the Welcome box"
+msgstr ""
+
+#: forum/settings/sidebar.py:11
+msgid "Do you want to show the welcome box when a user first visits your site."
+msgstr ""
+
+#: forum/settings/sidebar.py:15
+msgid "Application intro"
+msgstr ""
+
+#: forum/settings/sidebar.py:16
+msgid ""
+"The introductory page that is visible in the sidebar for anonymous users."
+msgstr ""
+
+#: forum/settings/sidebar.py:46
+msgid "Upper block rendering mode"
+msgstr ""
+
+#: forum/settings/sidebar.py:47
+msgid "How to render your upper block code."
+msgstr ""
+
+#: forum/settings/sidebar.py:75
+msgid "Lower block rendering mode"
+msgstr ""
+
+#: forum/settings/sidebar.py:76
+msgid "How to render your lower block code."
+msgstr ""
+
+#: forum/settings/static.py:17
+msgid "Use custom CSS"
+msgstr ""
+
+#: forum/settings/static.py:18
+msgid "Do you want to use custom CSS."
+msgstr ""
+
+#: forum/settings/static.py:22
+msgid "Custom CSS"
+msgstr ""
+
+#: forum/settings/static.py:23
+msgid "Your custom CSS."
+msgstr ""
+
+#: forum/settings/static.py:31
+msgid "Use custom header"
+msgstr ""
+
+#: forum/settings/static.py:32
+msgid "Do you want to use a custom header."
+msgstr ""
+
+#: forum/settings/static.py:36
+msgid "Custom Header"
+msgstr ""
+
+#: forum/settings/static.py:37
+msgid "Your custom header."
+msgstr ""
+
+#: forum/settings/static.py:42
+msgid "Custom Header rendering mode"
+msgstr ""
+
+#: forum/settings/static.py:43
+msgid "How to render your custom header code."
+msgstr ""
+
+#: forum/settings/static.py:48
+msgid "Show announcement bar"
+msgstr ""
+
+#: forum/settings/static.py:49
+msgid ""
+"Some piece of content that goes under the search bar and can be used for "
+"announcements, etc."
+msgstr ""
+
+#: forum/settings/static.py:53
+msgid "Announcement bar"
+msgstr ""
+
+#: forum/settings/static.py:54
+msgid "The announcement bar content."
+msgstr ""
+
+#: forum/settings/static.py:59
+msgid "Announcement bar rendering mode"
+msgstr ""
+
+#: forum/settings/static.py:60
+msgid "How to render your announcement bar code."
+msgstr ""
+
+#: forum/settings/static.py:65
+msgid "Use custom footer"
+msgstr ""
+
+#: forum/settings/static.py:66
+msgid "Do you want to use a custom footer."
+msgstr ""
+
+#: forum/settings/static.py:70
+msgid "Custom Footer"
+msgstr ""
+
+#: forum/settings/static.py:71
+#, fuzzy
+msgid "Your custom footer."
+msgstr ""
+"<strong>Your new Email:</strong> (will <strong>not</strong> be shown to "
+"anyone, must be valid)"
+
+#: forum/settings/static.py:76
+msgid "Custom footer rendering mode"
+msgstr ""
+
+#: forum/settings/static.py:77
+msgid "How to render your custom footer code."
+msgstr ""
+
+#: forum/settings/static.py:82
+msgid "Replace default footer"
+msgstr ""
+
+#: forum/settings/static.py:83
+msgid "Above default footer"
+msgstr ""
+
+#: forum/settings/static.py:84
+msgid "Below default footer"
+msgstr ""
+
+#: forum/settings/static.py:88
+msgid "Custom Footer Mode"
+msgstr ""
+
+#: forum/settings/static.py:89
+msgid "How your custom footer will appear."
+msgstr ""
+
+#: forum/settings/static.py:98
+msgid "Use custom Head elements"
+msgstr ""
+
+#: forum/settings/static.py:99
+msgid "Do you want to use custom head elements."
+msgstr ""
+
+#: forum/settings/static.py:103
+msgid "Custom Head"
+msgstr ""
+
+#: forum/settings/static.py:104
+msgid "Your custom Head elements."
+msgstr ""
+
+#: forum/settings/upload.py:5
+msgid "File upload settings"
+msgstr ""
+
+#: forum/settings/upload.py:5
+msgid "File uploads related settings."
+msgstr ""
+
+#: forum/settings/upload.py:8
+msgid "Uploaded files folder"
+msgstr ""
+
+#: forum/settings/upload.py:9
+msgid ""
+"The filesystem path where uploaded files will be stored. Please note that "
+"this folder must exist."
+msgstr ""
+
+#: forum/settings/upload.py:12
+msgid "Uploaded files alias"
+msgstr ""
+
+#: forum/settings/upload.py:13
+msgid ""
+"The url alias for uploaded files. Notice that if you change this setting, "
+"you'll need to restart your site."
+msgstr ""
+
+#: forum/settings/upload.py:16
+msgid "Max file size"
+msgstr ""
+
+#: forum/settings/upload.py:17
+msgid "The maximum allowed file size for uploads in mb."
+msgstr ""
+
+#: forum/settings/urls.py:4
+msgid "URL settings"
+msgstr ""
+
+#: forum/settings/urls.py:4
+msgid "Some settings to tweak behaviour of site urls (experimental)."
+msgstr ""
+
+#: forum/settings/urls.py:7
+msgid "Allow unicode in slugs"
+msgstr ""
+
+#: forum/settings/urls.py:8
+msgid "Allow unicode/non-latin characters in urls."
+msgstr ""
+
+#: forum/settings/urls.py:12
+msgid "Force single url"
+msgstr ""
+
+#: forum/settings/urls.py:13
+msgid ""
+"Redirect the request in case there is a mismatch between the slug in the url "
+"and the actual slug"
+msgstr ""
+
+#: forum/settings/users.py:7
+#, fuzzy
+msgid "Users settings"
+msgstr ""
+"<span class='big strong'>Adjust frequency of email updates.</span> Receive "
+"updates on interesting questions by email, <strong><br/>help the community</"
+"strong> by answering questions of your colleagues. If you do not wish to "
+"receive emails - select 'no email' on all items below.<br/>Updates are only "
+"sent when there is any new activity on selected items."
+
+#: forum/settings/users.py:7
+#, fuzzy
+msgid "General settings for the OSQA users."
+msgstr "Поздрави от Zapprotect Q&A"
+
+#: forum/settings/users.py:10
+#, fuzzy
+msgid "Editable screen name"
+msgstr "Публично име"
+
+#: forum/settings/users.py:11
+msgid "Allow users to alter their screen name."
+msgstr ""
+
+#: forum/settings/users.py:15
+msgid "Minimum username length"
+msgstr ""
+
+#: forum/settings/users.py:16
+msgid "The minimum length (in character) of a username."
+msgstr ""
+
+#: forum/settings/users.py:19
+msgid "fuck"
+msgstr ""
+
+#: forum/settings/users.py:19
+msgid "shit"
+msgstr ""
+
+#: forum/settings/users.py:19
+#, fuzzy
+msgid "ass"
+msgstr "отговори"
+
+#: forum/settings/users.py:19
+msgid "sex"
+msgstr ""
+
+#: forum/settings/users.py:19
+#, fuzzy
+msgid "add"
+msgstr "Добави"
+
+#: forum/settings/users.py:19 forum/templatetags/node_tags.py:94
+msgid "edit"
+msgstr "редактирай"
+
+#: forum/settings/users.py:19 forum/views/auth.py:382 forum/views/auth.py:387
+#, fuzzy
+msgid "save"
+msgstr "сребро"
+
+#: forum/settings/users.py:19 forum/templatetags/node_tags.py:118
+msgid "delete"
+msgstr ""
+
+#: forum/settings/users.py:19
+#, fuzzy
+msgid "manage"
+msgstr "снимка"
+
+#: forum/settings/users.py:19
+#, fuzzy
+msgid "update"
+msgstr "обновено"
+
+#: forum/settings/users.py:19
+#: forum/skins/default/templates/auth/auth_settings.html:12
+#: forum/skins/zapprotect/templates/auth/auth_settings.html:12
+msgid "remove"
+msgstr "премахни"
+
+#: forum/settings/users.py:19
+msgid "new"
+msgstr ""
+
+#: forum/settings/users.py:21
+#, fuzzy
+msgid "Disabled usernames"
+msgstr "Choose screen name"
+
+#: forum/settings/users.py:22
+msgid ""
+"A comma separated list of disabled usernames (usernames not allowed during a "
+"new user registration)."
+msgstr ""
+
+#: forum/settings/users.py:26
+msgid "Show status diamonds"
+msgstr ""
+
+#: forum/settings/users.py:27
+msgid "Show status \"diamonds\" next to moderators or superusers usernames."
+msgstr ""
+
+#: forum/settings/users.py:32
+#, fuzzy
+msgid "Force unique email"
+msgstr ""
+"<strong>Нов имейл:</strong> (няма да бъде споделян, трябва да бъде "
+"действителен)"
+
+#: forum/settings/users.py:33
+msgid "Should each user have an unique email."
+msgstr ""
+
+#: forum/settings/users.py:37
+msgid "Require email validation to..."
+msgstr ""
+
+#: forum/settings/users.py:38
+msgid ""
+"Which actions in this site, users without a valid email will be prevented "
+"from doing."
+msgstr ""
+
+#: forum/settings/users.py:40
+#, fuzzy
+msgid "ask questions"
+msgstr "задай въпрос"
+
+#: forum/settings/users.py:40
+#, fuzzy
+msgid "provide answers"
+msgstr "най-старите"
+
+#: forum/settings/users.py:40
+#, fuzzy
+msgid "make comments"
+msgstr "post a comment"
+
+#: forum/settings/users.py:40
+#, fuzzy
+msgid "report posts"
+msgstr "karma"
+
+#: forum/settings/users.py:45
+msgid "Don't notify to invalid emails"
+msgstr ""
+
+#: forum/settings/users.py:46
+msgid "Do not notify users with unvalidated emails."
+msgstr ""
+
+#: forum/settings/users.py:50
+msgid "Hold pending posts for X minutes"
+msgstr ""
+
+#: forum/settings/users.py:51
+msgid ""
+"How much time in minutes a post should be kept in session until the user "
+"logs in or validates the email."
+msgstr ""
+
+#: forum/settings/users.py:55
+msgid "Warn about pending posts afer X minutes"
+msgstr ""
+
+#: forum/settings/users.py:56
+msgid ""
+"How much time in minutes a user that just logged in or validated his email "
+"should be warned about a pending post instead of publishing it automatically."
+msgstr ""
+
+#: forum/settings/users.py:60
+msgid "suitable for display on all websites with any audience type."
+msgstr ""
+
+#: forum/settings/users.py:61
+msgid ""
+"may contain rude gestures, provocatively dressed individuals, the lesser "
+"swear words, or mild violence."
+msgstr ""
+
+#: forum/settings/users.py:62
+msgid ""
+"may contain such things as harsh profanity, intense violence, nudity, or "
+"hard drug use."
+msgstr ""
+
+#: forum/settings/users.py:63
+msgid "may contain hardcore sexual imagery or extremely disturbing violence."
+msgstr ""
+
+#: forum/settings/users.py:67
+#, fuzzy
+msgid "Gravatar rating"
+msgstr ""
+"<strong>Gravatar</strong> means <strong>g</strong>lobally <strong>r</"
+"strong>ecognized <strong>avatar</strong> - your unique avatar image "
+"associated with your email address. It's simply a picture that shows next to "
+"your posts on the websites that support gravatar protocol. By default gravar "
+"appears as a square filled with a snowflake-like figure. You can <strong>set "
+"your image</strong> at <a href='http://gravatar.com'><strong>gravatar.com</"
+"strong></a>"
+
+#: forum/settings/users.py:68
+msgid ""
+"Gravatar allows users to self-rate their images so that they can indicate if "
+"an image is appropriate for a certain audience."
+msgstr ""
+
+#: forum/settings/users.py:74
+msgid ""
+"(mystery-man) a simple, cartoon-style silhouetted outline of a person (does "
+"not vary by email hash)"
+msgstr ""
+
+#: forum/settings/users.py:75
+msgid "a geometric pattern based on an email hash"
+msgstr ""
+
+#: forum/settings/users.py:76
+msgid "a generated \"monster\" with different colors, faces, etc"
+msgstr ""
+
+#: forum/settings/users.py:77
+msgid "generated faces with differing features and backgrounds"
+msgstr ""
+
+#: forum/settings/users.py:81
+#, fuzzy
+msgid "Gravatar default"
+msgstr ""
+"<strong>Gravatar</strong> means <strong>g</strong>lobally <strong>r</"
+"strong>ecognized <strong>avatar</strong> - your unique avatar image "
+"associated with your email address. It's simply a picture that shows next to "
+"your posts on the websites that support gravatar protocol. By default gravar "
+"appears as a square filled with a snowflake-like figure. You can <strong>set "
+"your image</strong> at <a href='http://gravatar.com'><strong>gravatar.com</"
+"strong></a>"
+
+#: forum/settings/users.py:82
+msgid ""
+"Gravatar has a number of built in options which you can also use as defaults."
+msgstr ""
+
+#: forum/settings/view.py:5
+msgid "View settings"
+msgstr ""
+
+#: forum/settings/view.py:5
+msgid "Set up how certain parts of the site are displayed."
+msgstr ""
+
+#: forum/settings/view.py:8
+msgid "Recent tags block size"
+msgstr ""
+
+#: forum/settings/view.py:9
+msgid ""
+"The number of tags to display in the recent tags block in the front page."
+msgstr ""
+
+#: forum/settings/view.py:12
+#, fuzzy
+msgid "Recent awards block size"
+msgstr "Recent badges"
+
+#: forum/settings/view.py:13
+msgid ""
+"The number of awards to display in the recent awards block in the front page."
+msgstr ""
+
+#: forum/settings/view.py:16
+#, fuzzy
+msgid "Limit related tags block"
+msgstr "Tags"
+
+#: forum/settings/view.py:17
+msgid ""
+"Limit related tags block size in questions list pages. Set to 0 to display "
+"all all tags."
+msgstr ""
+
+#: forum/settings/voting.py:4
+msgid "Voting rules"
+msgstr ""
+
+#: forum/settings/voting.py:4
+msgid "Configure the voting rules on your site."
+msgstr ""
+
+#: forum/settings/voting.py:7
+msgid "Maximum votes per day"
+msgstr ""
+
+#: forum/settings/voting.py:8
+msgid "The maximum number of votes an user can cast per day."
+msgstr ""
+
+#: forum/settings/voting.py:11
+msgid "Start warning about votes left"
+msgstr ""
+
+#: forum/settings/voting.py:12
+msgid "From how many votes left should an user start to be warned about it."
+msgstr ""
+
+#: forum/settings/voting.py:15
+msgid "Maximum flags per day"
+msgstr ""
+
+#: forum/settings/voting.py:16
+msgid "The maximum number of times an can flag a post per day."
+msgstr ""
+
+#: forum/settings/voting.py:19
+msgid "Flag count to hide post"
+msgstr ""
+
+#: forum/settings/voting.py:20
+msgid ""
+"How many times a post needs to be flagged to be hidden from the main page."
+msgstr ""
+
+#: forum/settings/voting.py:23
+msgid "Flag count to delete post"
+msgstr ""
+
+#: forum/settings/voting.py:24
+msgid "How many times a post needs to be flagged to be deleted."
+msgstr ""
+
+#: forum/settings/voting.py:27
+msgid "Days to cancel a vote"
+msgstr ""
+
+#: forum/settings/voting.py:28
+msgid "How many days an user can cancel a vote after he originaly casted it."
+msgstr ""
+
+#: forum/skins/default/templates/401.html:3
+#: forum/skins/default/templates/401.html:28
+#: forum/skins/zapprotect/templates/401.html:3
+#: forum/skins/zapprotect/templates/401.html:28
+msgid "Not logged in"
+msgstr ""
+
+#: forum/skins/default/templates/401.html:32
+#: forum/skins/zapprotect/templates/401.html:32
+msgid "You are not logged in..."
+msgstr ""
+
+#: forum/skins/default/templates/401.html:34
+#: forum/skins/zapprotect/templates/401.html:34
+msgid "...and the resource you're trying to access is pretocted."
+msgstr ""
+
+#: forum/skins/default/templates/401.html:36
+#: forum/skins/zapprotect/templates/401.html:36
+msgid "Redirecting to the login page."
+msgstr ""
+
+#: forum/skins/default/templates/401.html:39
+#: forum/skins/zapprotect/templates/401.html:39
+msgid "If you're not automatically redirected in 5 seconds, please click"
+msgstr ""
+
+#: forum/skins/default/templates/401.html:40
+#: forum/skins/default/templates/auth/signin.html:102
+#: forum/skins/default/templates/notifications/base.html:27
+#: forum/skins/zapprotect/templates/401.html:40
+#: forum/skins/zapprotect/templates/auth/signin.html:102
+#: forum/skins/zapprotect/templates/notifications/base.html:27
+msgid "here"
+msgstr "тук"
+
+#: forum/skins/default/templates/403.html:3
+#: forum/skins/default/templates/403.html:11
+#: forum/skins/zapprotect/templates/403.html:3
+#: forum/skins/zapprotect/templates/403.html:11
+msgid "Forbidden"
+msgstr "Забранено"
+
+#: forum/skins/default/templates/403.html:15
+#: forum/skins/zapprotect/templates/403.html:15
+msgid "Sorry, you don't have permissions to access this page."
+msgstr "Съжалявам, но нямате право да разглеждате тази страница."
+
+#: forum/skins/default/templates/403.html:17
+#: forum/skins/default/templates/404.html:26
+#: forum/skins/zapprotect/templates/403.html:17
+#: forum/skins/zapprotect/templates/404.html:26
+msgid "This might have happened for the following reasons:"
+msgstr "Това може да е станало поради следните причини:"
+
+#: forum/skins/default/templates/403.html:19
+#: forum/skins/zapprotect/templates/403.html:19
+msgid ""
+"you followed a link on an email, but you're currently logged in as another "
+"user;"
+msgstr ""
+"използвахте линк от имейл, но в момента сте влезнали като друг потребител"
+
+#: forum/skins/default/templates/403.html:20
+#: forum/skins/zapprotect/templates/403.html:20
+msgid "there are errors in the url, please confirm it;"
+msgstr "има грешки в адреса, моля проверете го;"
+
+#: forum/skins/default/templates/403.html:21
+#: forum/skins/zapprotect/templates/403.html:21
+#, fuzzy
+msgid "if you believe you shouldn't bee seeing this error, please"
+msgstr "ако смятате, че тази страница 404 не е трябвало да се показва"
+
+#: forum/skins/default/templates/403.html:23
+#: forum/skins/default/templates/404.html:31
+#: forum/skins/zapprotect/templates/403.html:23
+#: forum/skins/zapprotect/templates/404.html:31
+msgid "report this problem"
+msgstr "оповестете за проблема"
+
+#: forum/skins/default/templates/403.html:29
+#: forum/skins/zapprotect/templates/403.html:29
+#, fuzzy
+msgid "to home page"
+msgstr "обратно на началната страница"
+
+#: forum/skins/default/templates/403.html:30
+#: forum/skins/default/templates/404.html:41
+#: forum/skins/zapprotect/templates/403.html:30
+#: forum/skins/zapprotect/templates/404.html:41
+msgid "see all questions"
+msgstr "вижте всички въпроси"
+
+#: forum/skins/default/templates/403.html:31
+#: forum/skins/default/templates/404.html:42
+#: forum/skins/zapprotect/templates/403.html:31
+#: forum/skins/zapprotect/templates/404.html:42
+msgid "see all tags"
+msgstr "вижте всички тагове"
+
+#: forum/skins/default/templates/404.html:4
+#: forum/skins/zapprotect/templates/404.html:4
+msgid "404 Error"
+msgstr "Грешка 404"
+
+#: forum/skins/default/templates/404.html:20
+#: forum/skins/zapprotect/templates/404.html:20
+#, fuzzy
+msgid "404 Not Found"
+msgstr "Нищо не беше намерено"
+
+#: forum/skins/default/templates/404.html:24
+#: forum/skins/zapprotect/templates/404.html:24
+msgid "Sorry, could not find the page you requested."
+msgstr "За съжаление търсената страница не беше намерена."
+
+#: forum/skins/default/templates/404.html:28
+#: forum/skins/zapprotect/templates/404.html:28
+msgid "this question or answer has been deleted;"
+msgstr "този въпрос или отговор е бил изтрит;"
+
+#: forum/skins/default/templates/404.html:29
+#: forum/skins/zapprotect/templates/404.html:29
+msgid "url has error - please check it;"
+msgstr "адреса има грешка -- проверете го;"
+
+#: forum/skins/default/templates/404.html:30
+#: forum/skins/zapprotect/templates/404.html:30
+#, fuzzy
+msgid "if you believe this error 404 should not have occurred, please"
+msgstr "ако смятате, че тази страница 404 не е трябвало да се показва"
+
+#: forum/skins/default/templates/404.html:40
+#: forum/skins/default/templates/500.html:27
+#: forum/skins/zapprotect/templates/404.html:40
+#: forum/skins/zapprotect/templates/500.html:27
+msgid "back to previous page"
+msgstr "върнете се на предишната страница"
+
+#: forum/skins/default/templates/500.html:22
+#: forum/skins/zapprotect/templates/500.html:22
+msgid "sorry, system error"
+msgstr "съжаляваме, системна грешка"
+
+#: forum/skins/default/templates/500.html:24
+#: forum/skins/zapprotect/templates/500.html:24
+msgid "system error log is recorded, error will be fixed as soon as possible"
+msgstr "системния лог е записан, грешката ще бъде оправена възможно най-скоро"
+
+#: forum/skins/default/templates/500.html:25
+#: forum/skins/zapprotect/templates/500.html:25
+msgid "please report the error to the site administrators if you wish"
+msgstr "моля, споделете грешката с администраторите на сайта"
+
+#: forum/skins/default/templates/500.html:28
+#: forum/skins/zapprotect/templates/500.html:28
+msgid "see latest questions"
+msgstr "вижте последните въпроси"
+
+#: forum/skins/default/templates/500.html:29
+#: forum/skins/zapprotect/templates/500.html:29
+msgid "see tags"
+msgstr "виж таговете"
+
+#: forum/skins/default/templates/503.html:6
+#: forum/skins/default/templates/503.html:17
+#: forum/skins/zapprotect/templates/503.html:6
+#: forum/skins/zapprotect/templates/503.html:17
+msgid "System down for maintenance"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:4
+#: forum/skins/zapprotect/templates/account_settings.html:4
+msgid "Account functions"
+msgstr "Функции на профила"
+
+#: forum/skins/default/templates/account_settings.html:29
+#: forum/skins/default/templates/auth/auth_settings.html:33
+#: forum/skins/zapprotect/templates/account_settings.html:29
+#: forum/skins/zapprotect/templates/auth/auth_settings.html:33
+msgid "Change password"
+msgstr "Смяна на паролата"
+
+#: forum/skins/default/templates/account_settings.html:30
+#: forum/skins/zapprotect/templates/account_settings.html:30
+msgid "Give your  account a new password."
+msgstr "Предоставете нова парола за профила си."
+
+#: forum/skins/default/templates/account_settings.html:32
+#: forum/skins/zapprotect/templates/account_settings.html:32
+msgid "Change email "
+msgstr "Промяна на имейла "
+
+#: forum/skins/default/templates/account_settings.html:33
+#: forum/skins/zapprotect/templates/account_settings.html:33
+msgid "Add or update the email address associated with your account."
+msgstr "Добавете или променете имейла асоцииран с Вашия акаунт."
+
+#: forum/skins/default/templates/account_settings.html:35
+#: forum/skins/zapprotect/templates/account_settings.html:35
+msgid "Change OpenID"
+msgstr "Промени OpenID"
+
+#: forum/skins/default/templates/account_settings.html:36
+#: forum/skins/zapprotect/templates/account_settings.html:36
+msgid "Change openid associated to your account"
+msgstr "Променете OpenID свързан с Вашия акаунт"
+
+#: forum/skins/default/templates/account_settings.html:39
+#: forum/skins/zapprotect/templates/account_settings.html:39
+msgid "Delete account"
+msgstr "Изтрий профила"
+
+#: forum/skins/default/templates/account_settings.html:40
+#: forum/skins/zapprotect/templates/account_settings.html:40
+msgid "Erase your username and all your data from website"
+msgstr "Изтрий потребителя и цялата информация от сайта"
+
+#: forum/skins/default/templates/answer_edit.html:5
+#: forum/skins/default/templates/answer_edit.html:62
+#: forum/skins/zapprotect/templates/answer_edit.html:5
+#: forum/skins/zapprotect/templates/answer_edit.html:62
+msgid "Edit answer"
+msgstr "Редактирай отговора"
+
+#: forum/skins/default/templates/answer_edit.html:19
+#: forum/skins/default/templates/answer_edit.html:22
+#: forum/skins/default/templates/ask.html:26
+#: forum/skins/default/templates/ask.html:29
+#: forum/skins/default/templates/question.html:38
+#: forum/skins/default/templates/question.html:41
+#: forum/skins/default/templates/question_edit.html:19
+#: forum/skins/default/templates/question_edit.html:22
+#: forum/skins/zapprotect/templates/answer_edit.html:19
+#: forum/skins/zapprotect/templates/answer_edit.html:22
+#: forum/skins/zapprotect/templates/ask.html:26
+#: forum/skins/zapprotect/templates/ask.html:29
+#: forum/skins/zapprotect/templates/question.html:38
+#: forum/skins/zapprotect/templates/question.html:41
+#: forum/skins/zapprotect/templates/question_edit.html:19
+#: forum/skins/zapprotect/templates/question_edit.html:22
+msgid "hide preview"
+msgstr "скрий прегледа"
+
+#: forum/skins/default/templates/answer_edit.html:22
+#: forum/skins/default/templates/ask.html:29
+#: forum/skins/default/templates/question.html:41
+#: forum/skins/default/templates/question_edit.html:22
+#: forum/skins/zapprotect/templates/answer_edit.html:22
+#: forum/skins/zapprotect/templates/ask.html:29
+#: forum/skins/zapprotect/templates/question.html:41
+#: forum/skins/zapprotect/templates/question_edit.html:22
+msgid "show preview"
+msgstr "покажи прегледа"
+
+#: forum/skins/default/templates/answer_edit.html:62
+#: forum/skins/default/templates/question_edit.html:91
+#: forum/skins/default/templates/question_retag.html:58
+#: forum/skins/default/templates/revisions.html:38
+#: forum/skins/zapprotect/templates/answer_edit.html:62
+#: forum/skins/zapprotect/templates/question_edit.html:91
+#: forum/skins/zapprotect/templates/question_retag.html:58
+#: forum/skins/zapprotect/templates/revisions.html:38
+msgid "back"
+msgstr "назад"
+
+#: forum/skins/default/templates/answer_edit.html:67
+#: forum/skins/default/templates/question_edit.html:96
+#: forum/skins/default/templates/revisions.html:54
+#: forum/skins/zapprotect/templates/answer_edit.html:67
+#: forum/skins/zapprotect/templates/question_edit.html:96
+#: forum/skins/zapprotect/templates/revisions.html:54
+msgid "revision"
+msgstr "ревизия"
+
+#: forum/skins/default/templates/answer_edit.html:70
+#: forum/skins/default/templates/question_edit.html:100
+#: forum/skins/zapprotect/templates/answer_edit.html:70
+#: forum/skins/zapprotect/templates/question_edit.html:100
+msgid "select revision"
+msgstr "изберете ревизия"
+
+#: forum/skins/default/templates/answer_edit.html:77
+#: forum/skins/default/templates/ask.html:129
+#: forum/skins/default/templates/question.html:222
+#: forum/skins/default/templates/question_edit.html:117
+#: forum/skins/zapprotect/templates/answer_edit.html:77
+#: forum/skins/zapprotect/templates/ask.html:129
+#: forum/skins/zapprotect/templates/question.html:222
+#: forum/skins/zapprotect/templates/question_edit.html:117
+msgid "Toggle the real time Markdown editor preview"
+msgstr "Покажи визуалния текстов редактор"
+
+#: forum/skins/default/templates/answer_edit.html:77
+#: forum/skins/default/templates/ask.html:129
+#: forum/skins/default/templates/question.html:223
+#: forum/skins/default/templates/question_edit.html:117
+#: forum/skins/zapprotect/templates/answer_edit.html:77
+#: forum/skins/zapprotect/templates/ask.html:129
+#: forum/skins/zapprotect/templates/question.html:223
+#: forum/skins/zapprotect/templates/question_edit.html:117
+msgid "toggle preview"
+msgstr "покажи прегледа"
+
+#: forum/skins/default/templates/answer_edit.html:93
+#: forum/skins/default/templates/question_edit.html:144
+#: forum/skins/default/templates/question_retag.html:79
+#: forum/skins/zapprotect/templates/answer_edit.html:93
+#: forum/skins/zapprotect/templates/question_edit.html:144
+#: forum/skins/zapprotect/templates/question_retag.html:79
+msgid "Save edit"
+msgstr "Запази промените"
+
+#: forum/skins/default/templates/answer_edit.html:94
+#: forum/skins/default/templates/base_content.html:34
+#: forum/skins/default/templates/close.html:29
+#: forum/skins/default/templates/feedback.html:50
+#: forum/skins/default/templates/question_edit.html:145
+#: forum/skins/default/templates/question_retag.html:80
+#: forum/skins/default/templates/reopen.html:30
+#: forum/skins/default/templates/users/edit.html:99
+#: forum/skins/zapprotect/templates/answer_edit.html:94
+#: forum/skins/zapprotect/templates/base_content.html:34
+#: forum/skins/zapprotect/templates/close.html:29
+#: forum/skins/zapprotect/templates/feedback.html:50
+#: forum/skins/zapprotect/templates/question_edit.html:145
+#: forum/skins/zapprotect/templates/question_retag.html:80
+#: forum/skins/zapprotect/templates/reopen.html:30
+#: forum/skins/zapprotect/templates/users/edit.html:99
+msgid "Cancel"
+msgstr "Откажи"
+
+#: forum/skins/default/templates/answer_edit_tips.html:4
+#: forum/skins/zapprotect/templates/answer_edit_tips.html:4
+msgid "answer tips"
+msgstr "Съвети"
+
+#: forum/skins/default/templates/answer_edit_tips.html:7
+#: forum/skins/zapprotect/templates/answer_edit_tips.html:7
+msgid "please make your answer relevant to this community"
+msgstr "направете отговора подходящ за общността"
+
+#: forum/skins/default/templates/answer_edit_tips.html:10
+#: forum/skins/zapprotect/templates/answer_edit_tips.html:10
+msgid "try to give an answer, rather than engage into a discussion"
+msgstr "опитайте се да отговорите, а не изисквайте дискусия"
+
+#: forum/skins/default/templates/answer_edit_tips.html:13
+#: forum/skins/zapprotect/templates/answer_edit_tips.html:13
+msgid "please try to provide details"
+msgstr "опитайте се да предоставите детайлна информация"
+
+#: forum/skins/default/templates/answer_edit_tips.html:16
+#: forum/skins/default/templates/question_edit_tips.html:18
+#: forum/skins/zapprotect/templates/answer_edit_tips.html:16
+#: forum/skins/zapprotect/templates/question_edit_tips.html:18
+msgid "be clear and concise"
+msgstr "бъдете кратки и ясни"
+
+#: forum/skins/default/templates/answer_edit_tips.html:20
+#: forum/skins/default/templates/question_edit_tips.html:22
+#: forum/skins/zapprotect/templates/answer_edit_tips.html:20
+#: forum/skins/zapprotect/templates/question_edit_tips.html:22
+msgid "see frequently asked questions"
+msgstr "вижте често задаваните въпроси"
+
+#: forum/skins/default/templates/ask.html:4
+#: forum/skins/default/templates/ask.html:92
+#: forum/skins/zapprotect/templates/ask.html:4
+#: forum/skins/zapprotect/templates/ask.html:92
+msgid "Ask a question"
+msgstr "Задайте въпрос"
+
+#: forum/skins/default/templates/ask.html:99
+#: forum/skins/zapprotect/templates/ask.html:99
+msgid "You are welcome to start submitting your question anonymously."
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:100
+#: forum/skins/zapprotect/templates/ask.html:100
+msgid ""
+"\n"
+"                    After submiting your question, you will be redirected to "
+"the login/signup page.\n"
+"                    Your question will be saved in the current session and "
+"will be published after you login with your existing account,\n"
+"                    or signup for a new account"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:104
+#: forum/skins/zapprotect/templates/ask.html:104
+msgid "and validate your email."
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:109
+#: forum/skins/zapprotect/templates/ask.html:109
+msgid ""
+"Remember, your question will not be published until you validate your email."
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:110
+#: forum/skins/default/templates/question.html:208
+#: forum/skins/default/templates/users/info.html:86
+#: forum/skins/zapprotect/templates/ask.html:110
+#: forum/skins/zapprotect/templates/question.html:208
+#: forum/skins/zapprotect/templates/users/info.html:86
+msgid "Send me a validation link."
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:145
+#: forum/skins/zapprotect/templates/ask.html:145
+msgid "(required)"
+msgstr "(задължително)"
+
+#: forum/skins/default/templates/ask.html:152
+#: forum/skins/zapprotect/templates/ask.html:152
+msgid "Login/signup to post your question"
+msgstr "Оторизирайте се за да публикувате"
+
+#: forum/skins/default/templates/ask.html:154
+#: forum/skins/zapprotect/templates/ask.html:154
+msgid "Ask your question"
+msgstr "Задайте Вашия въпрос"
+
+#: forum/skins/default/templates/badge.html:7
+#: forum/skins/default/templates/badge.html:18
+#: forum/skins/zapprotect/templates/badge.html:7
+#: forum/skins/zapprotect/templates/badge.html:18
+msgid "Badge"
+msgstr "Точка"
+
+#: forum/skins/default/templates/badge.html:27
+#: forum/skins/zapprotect/templates/badge.html:27
+msgid "The users have been awarded with badges:"
+msgstr "Потребителя е награден с точки:"
+
+#: forum/skins/default/templates/badges.html:6
+#: forum/skins/zapprotect/templates/badges.html:6
+msgid "Badges summary"
+msgstr "Обобщение за точките"
+
+#: forum/skins/default/templates/badges.html:9
+#: forum/skins/zapprotect/templates/badges.html:9
+msgid "Badges"
+msgstr "Точки"
+
+#: forum/skins/default/templates/badges.html:13
+#: forum/skins/zapprotect/templates/badges.html:13
+msgid "Community gives you awards for your questions, answers and votes."
+msgstr ""
+"Ако Вашите отговори са ползотворни, общността ще Ви се отблагодари с точки."
+
+#: forum/skins/default/templates/badges.html:14
+#: forum/skins/zapprotect/templates/badges.html:14
+#, fuzzy
+msgid ""
+"Below is the list of available badges and number of times each type of badge "
+"has been awarded.\n"
+"    "
+msgstr ""
+"Currently badges differ only by their level: <strong>gold</strong>, "
+"<strong>silver</strong> and <strong>bronze</strong> (their meanings are "
+"described on the right). In the future there will be many types of badges at "
+"each level. <strong>Please give us your <a href='%(feedback_faq_url)"
+"s'>feedback</a></strong> - what kinds of badges would you like to see and "
+"suggest the activity for which those badges might be awarded."
+
+#: forum/skins/default/templates/badges.html:41
+#: forum/skins/zapprotect/templates/badges.html:41
+msgid "Community badges"
+msgstr "Badge levels"
+
+#: forum/skins/default/templates/badges.html:44
+#: forum/skins/zapprotect/templates/badges.html:44
+msgid "gold badge: the highest honor and is very rare"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:44
+#: forum/skins/zapprotect/templates/badges.html:44
+msgid "gold"
+msgstr "злато"
+
+#: forum/skins/default/templates/badges.html:47
+#: forum/skins/zapprotect/templates/badges.html:47
+msgid "gold badge description"
+msgstr ""
+"Gold badge is the highest award in this community. To obtain it have to show "
+"profound knowledge and ability in addition to your active participation."
+
+#: forum/skins/default/templates/badges.html:51
+#: forum/skins/zapprotect/templates/badges.html:51
+msgid ""
+"silver badge: occasionally awarded for the very high quality contributions"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:52
+#: forum/skins/zapprotect/templates/badges.html:52
+msgid "silver"
+msgstr "сребро"
+
+#: forum/skins/default/templates/badges.html:55
+#: forum/skins/zapprotect/templates/badges.html:55
+msgid "silver badge description"
+msgstr ""
+"Obtaining silver badge requires significant patience. If you have received "
+"one, that means you have greatly contributed to this community."
+
+#: forum/skins/default/templates/badges.html:58
+#: forum/skins/zapprotect/templates/badges.html:58
+msgid "bronze badge: often given as a special honor"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:59
+#: forum/skins/zapprotect/templates/badges.html:59
+msgid "bronze"
+msgstr "бронз"
+
+#: forum/skins/default/templates/badges.html:62
+#: forum/skins/zapprotect/templates/badges.html:62
+msgid "bronze badge description"
+msgstr ""
+"If you are an active participant in this community, you will be recognized "
+"with this badge."
+
+#: forum/skins/default/templates/base_content.html:30
+#: forum/skins/zapprotect/templates/base_content.html:30
+msgid "Are you sure?"
+msgstr ""
+
+#: forum/skins/default/templates/base_content.html:31
+#: forum/skins/zapprotect/templates/base_content.html:31
+msgid "Yes"
+msgstr ""
+
+#: forum/skins/default/templates/base_content.html:32
+#: forum/skins/zapprotect/templates/base_content.html:32
+msgid "No"
+msgstr ""
+
+#: forum/skins/default/templates/base_content.html:33
+#: forum/skins/zapprotect/templates/base_content.html:33
+#, fuzzy
+msgid "Message:"
+msgstr "Вашето съобщение:"
+
+#: forum/skins/default/templates/base_content.html:35
+#: forum/skins/zapprotect/templates/base_content.html:35
+#, fuzzy
+msgid "Close"
+msgstr "[затворено]"
+
+#: forum/skins/default/templates/base_content.html:36
+#: forum/skins/zapprotect/templates/base_content.html:36
+msgid "Ok"
+msgstr ""
+
+#: forum/skins/default/templates/base_content.html:38
+#: forum/skins/zapprotect/templates/base_content.html:38
+#: forum/templatetags/node_tags.py:151
+#, fuzzy
+msgid "word"
+msgstr "парола"
+
+#: forum/skins/default/templates/base_content.html:39
+#: forum/skins/zapprotect/templates/base_content.html:39
+#, fuzzy
+msgid "words"
+msgstr "парола"
+
+#: forum/skins/default/templates/base_content.html:40
+#: forum/skins/zapprotect/templates/base_content.html:40
+#: forum/templatetags/node_tags.py:150
+#, fuzzy
+msgid "character"
+msgstr ""
+"#-#-#-#-#  django.pot (PACKAGE VERSION)  #-#-#-#-#\n"
+"#-#-#-#-#  django.pot (PACKAGE VERSION)  #-#-#-#-#\n"
+
+#: forum/skins/default/templates/base_content.html:41
+#: forum/skins/zapprotect/templates/base_content.html:41
+msgid "characters"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:6
+#: forum/skins/default/templates/close.html:16
+#: forum/skins/zapprotect/templates/close.html:6
+#: forum/skins/zapprotect/templates/close.html:16
+msgid "Close question"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:19
+#: forum/skins/zapprotect/templates/close.html:19
+msgid "Close the question"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:25
+#: forum/skins/zapprotect/templates/close.html:25
+msgid "Reasons"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:28
+#: forum/skins/zapprotect/templates/close.html:28
+msgid "OK to close"
+msgstr ""
+
+#: forum/skins/default/templates/email_base.html:32
+#: forum/skins/zapprotect/templates/email_base.html:32
+msgid "home"
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:6
+#: forum/skins/zapprotect/templates/feedback.html:6
+msgid "Feedback"
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:11
+#: forum/skins/zapprotect/templates/feedback.html:11
+msgid "Give us your feedback!"
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:17
+#: forum/skins/zapprotect/templates/feedback.html:17
+#, python-format
+msgid ""
+"\n"
+"            <span class='big strong'>Dear %(user_name)s</span>, we look "
+"forward to hearing your feedback. \n"
+"            Please type and send us your message below.\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:24
+#: forum/skins/zapprotect/templates/feedback.html:24
+msgid ""
+"\n"
+"            <span class='big strong'>Dear visitor</span>, we look forward to "
+"hearing your feedback.\n"
+"            Please type and send us your message below.\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:41
+#: forum/skins/zapprotect/templates/feedback.html:41
+msgid "(this field is required)"
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:49
+#: forum/skins/zapprotect/templates/feedback.html:49
+msgid "Send Feedback"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:8
+#: forum/skins/zapprotect/templates/header.html:8
+msgid "back to home page"
+msgstr "обратно на началната страница"
+
+#: forum/skins/default/templates/header.html:20
+#: forum/skins/zapprotect/templates/header.html:20
+msgid "ask a question"
+msgstr "задай въпрос"
+
+#: forum/skins/default/templates/header.html:30
+#: forum/skins/default/templates/opensearch.html:7
+#: forum/skins/default/templates/search.html:15
+#: forum/skins/zapprotect/templates/header.html:30
+#: forum/skins/zapprotect/templates/opensearch.html:7
+#: forum/skins/zapprotect/templates/search.html:15
+msgid "search"
+msgstr "търсене"
+
+#: forum/skins/default/templates/header.html:34
+#: forum/skins/default/templates/search.html:19
+#: forum/skins/zapprotect/templates/header.html:34
+#: forum/skins/zapprotect/templates/search.html:19 forum/views/readers.py:98
+#: forum/views/readers.py:100 forum/views/readers.py:139
+#: forum/views/users.py:317
+msgid "questions"
+msgstr "въпроси"
+
+#: forum/skins/default/templates/header.html:36
+#: forum/skins/default/templates/search.html:21
+#: forum/skins/zapprotect/templates/header.html:36
+#: forum/skins/zapprotect/templates/search.html:21 forum/views/users.py:59
+msgid "users"
+msgstr "потребители"
+
+#: forum/skins/default/templates/index.html:11
+#: forum/skins/zapprotect/templates/index.html:11
+#, fuzzy
+msgid "welcome to "
+msgstr "Добре дошли в Zapprotect Q&amp;A"
+
+#: forum/skins/default/templates/logout.html:6
+#: forum/skins/default/templates/logout.html:16
+#: forum/skins/zapprotect/templates/logout.html:6
+#: forum/skins/zapprotect/templates/logout.html:16
+msgid "Logout"
+msgstr "Изход"
+
+#: forum/skins/default/templates/logout.html:19
+#: forum/skins/zapprotect/templates/logout.html:19
+msgid ""
+"As a registered user you can login with your OpenID, log out of the site or "
+"permanently remove your account."
+msgstr ""
+"Clicking <strong>Logout</strong> will log you out from the forum, but will "
+"not sign you off from your OpenID provider.</p><p>If you wish to sign off "
+"completely - please make sure to log out from your OpenID provider as well."
+
+#: forum/skins/default/templates/logout.html:20
+#: forum/skins/zapprotect/templates/logout.html:20
+msgid "Logout now"
+msgstr "Излез сега"
+
+#: forum/skins/default/templates/markdown_help.html:6
+#: forum/skins/zapprotect/templates/markdown_help.html:6
+#, fuzzy
+msgid "Markdown Help"
+msgstr "Markdown съвети"
+
+#: forum/skins/default/templates/markdown_help.html:15
+#: forum/skins/zapprotect/templates/markdown_help.html:15
+#, fuzzy
+msgid "Markdown Syntax"
+msgstr "Markdown съвети"
+
+#: forum/skins/default/templates/markdown_help.html:16
+#: forum/skins/zapprotect/templates/markdown_help.html:16
+msgid ""
+"This document describes some of the more important parts of Markdown (for "
+"writers, that is).  There's a lot more to the syntax than is mentioned here, "
+"though.  To get the full syntax documentation, go to John Gruber's <a href="
+"\"http://daringfireball.net/projects/markdown/syntax\" rel=\"nofollow"
+"\">Markdown Syntax</a> page"
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:20
+#: forum/skins/zapprotect/templates/markdown_help.html:20
+#, fuzzy
+msgid "Headers"
+msgstr "Точки"
+
+#: forum/skins/default/templates/markdown_help.html:22
+#: forum/skins/zapprotect/templates/markdown_help.html:22
+msgid ""
+"For top-level headers underline the text with equal signs.  For second-level "
+"headers use dashes to underline."
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:26
+#: forum/skins/default/templates/markdown_help.html:30
+#: forum/skins/default/templates/markdown_help.html:49
+#: forum/skins/default/templates/markdown_help.html:52
+#: forum/skins/zapprotect/templates/markdown_help.html:26
+#: forum/skins/zapprotect/templates/markdown_help.html:30
+#: forum/skins/zapprotect/templates/markdown_help.html:49
+#: forum/skins/zapprotect/templates/markdown_help.html:52
+msgid "This is an H1"
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:36
+#: forum/skins/default/templates/markdown_help.html:40
+#: forum/skins/default/templates/markdown_help.html:58
+#: forum/skins/default/templates/markdown_help.html:61
+#: forum/skins/zapprotect/templates/markdown_help.html:36
+#: forum/skins/zapprotect/templates/markdown_help.html:40
+#: forum/skins/zapprotect/templates/markdown_help.html:58
+#: forum/skins/zapprotect/templates/markdown_help.html:61
+msgid "This is an H2"
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:45
+#: forum/skins/zapprotect/templates/markdown_help.html:45
+msgid ""
+"If you would rather, you can prefix headers with a hash (#) symbol instead.  "
+"The number of hash symbols indicates the header level.  For example, a "
+"single hash indicates a header level of one while two indicates the second "
+"header level:"
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:67
+#: forum/skins/default/templates/markdown_help.html:70
+#: forum/skins/zapprotect/templates/markdown_help.html:67
+#: forum/skins/zapprotect/templates/markdown_help.html:70
+msgid "This is an H3"
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:75
+#: forum/skins/zapprotect/templates/markdown_help.html:75
+msgid ""
+"Which you choose is a matter of style.  Whichever you thinks looks better in "
+"the text document.  In both cases, the final, fully formatted, document "
+"looks the same."
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:80
+#: forum/skins/zapprotect/templates/markdown_help.html:80
+msgid "Paragraphs"
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:82
+#: forum/skins/zapprotect/templates/markdown_help.html:82
+msgid "Paragraphs are surrounded by blank lines."
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:85
+#: forum/skins/zapprotect/templates/markdown_help.html:85
+msgid "This is paragraph one."
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:88
+#: forum/skins/zapprotect/templates/markdown_help.html:88
+msgid "This is paragraph two."
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:93
+#: forum/skins/zapprotect/templates/markdown_help.html:93
+#, fuzzy
+msgid "Links"
+msgstr "Вход"
+
+#: forum/skins/default/templates/markdown_help.html:95
+#: forum/skins/zapprotect/templates/markdown_help.html:95
+msgid ""
+"\n"
+"                There are two parts to every link.\n"
+"                The first is the actual text that the user will see and it "
+"is surrounded by brackets.\n"
+"                The second is address of the page you wish to link to and it "
+"is surrounded in parenthesis.\n"
+"                "
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:103
+#: forum/skins/default/templates/markdown_help.html:106
+#: forum/skins/zapprotect/templates/markdown_help.html:103
+#: forum/skins/zapprotect/templates/markdown_help.html:106
+msgid "link text"
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:103
+#: forum/skins/zapprotect/templates/markdown_help.html:103
+msgid "http://example.com/"
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:112
+#: forum/skins/zapprotect/templates/markdown_help.html:112
+msgid "Formatting"
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:114
+#: forum/skins/zapprotect/templates/markdown_help.html:114
+msgid ""
+"To indicate bold text surround the text with two star (*) symbols or two "
+"underscore (_) symbols:"
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:118
+#: forum/skins/default/templates/markdown_help.html:121
+#: forum/skins/zapprotect/templates/markdown_help.html:118
+#: forum/skins/zapprotect/templates/markdown_help.html:121
+msgid "This is bold"
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:126
+#: forum/skins/default/templates/markdown_help.html:129
+#: forum/skins/zapprotect/templates/markdown_help.html:126
+#: forum/skins/zapprotect/templates/markdown_help.html:129
+msgid "This is also bold"
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:134
+#: forum/skins/zapprotect/templates/markdown_help.html:134
+msgid ""
+"To indicate italicized text surround the text with a single star (*) symbol "
+"or underscore (_) symbol:"
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:138
+#: forum/skins/default/templates/markdown_help.html:141
+#: forum/skins/zapprotect/templates/markdown_help.html:138
+#: forum/skins/zapprotect/templates/markdown_help.html:141
+msgid "This is italics"
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:146
+#: forum/skins/default/templates/markdown_help.html:149
+#: forum/skins/zapprotect/templates/markdown_help.html:146
+#: forum/skins/zapprotect/templates/markdown_help.html:149
+msgid "This is also italics"
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:154
+#: forum/skins/zapprotect/templates/markdown_help.html:154
+msgid ""
+"To indicate italicized and bold text surround the text with three star (*) "
+"symbol or underscore (_) symbol:"
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:158
+#: forum/skins/default/templates/markdown_help.html:161
+#: forum/skins/zapprotect/templates/markdown_help.html:158
+#: forum/skins/zapprotect/templates/markdown_help.html:161
+msgid "This is bold and italics"
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:166
+#: forum/skins/default/templates/markdown_help.html:169
+#: forum/skins/zapprotect/templates/markdown_help.html:166
+#: forum/skins/zapprotect/templates/markdown_help.html:169
+msgid "This is also bold and italics"
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:176
+#: forum/skins/zapprotect/templates/markdown_help.html:176
+msgid "Blockquotes"
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:178
+#: forum/skins/zapprotect/templates/markdown_help.html:178
+msgid ""
+"To create an indented area use the right angle bracket (&gt;) character "
+"before each line to be included in the blockquote."
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:182
+#: forum/skins/default/templates/markdown_help.html:186
+#: forum/skins/default/templates/markdown_help.html:195
+#: forum/skins/default/templates/markdown_help.html:200
+#: forum/skins/zapprotect/templates/markdown_help.html:182
+#: forum/skins/zapprotect/templates/markdown_help.html:186
+#: forum/skins/zapprotect/templates/markdown_help.html:195
+#: forum/skins/zapprotect/templates/markdown_help.html:200
+msgid "This is part of a blockquote."
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:183
+#: forum/skins/default/templates/markdown_help.html:186
+#: forum/skins/zapprotect/templates/markdown_help.html:183
+#: forum/skins/zapprotect/templates/markdown_help.html:186
+msgid "This is part of the same blockquote."
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:191
+#: forum/skins/zapprotect/templates/markdown_help.html:191
+msgid ""
+"Rather than putting it in front of each line to include in the block quote "
+"you can put it at the beginning and end the quote with a newline."
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:196
+#: forum/skins/default/templates/markdown_help.html:200
+#: forum/skins/zapprotect/templates/markdown_help.html:196
+#: forum/skins/zapprotect/templates/markdown_help.html:200
+msgid "This continues the blockquote even though there's no bracket."
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:197
+#: forum/skins/default/templates/markdown_help.html:201
+#: forum/skins/zapprotect/templates/markdown_help.html:197
+#: forum/skins/zapprotect/templates/markdown_help.html:201
+msgid "The blank line ends the blockquote."
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:207
+#: forum/skins/zapprotect/templates/markdown_help.html:207
+msgid "Lists"
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:209
+#: forum/skins/zapprotect/templates/markdown_help.html:209
+msgid ""
+"To create a numbered list in Markdown, prefix each item in the list with a "
+"number followed by a period and space.  The number you use actually doesn't "
+"matter."
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:213
+#: forum/skins/default/templates/markdown_help.html:214
+#: forum/skins/default/templates/markdown_help.html:215
+#: forum/skins/default/templates/markdown_help.html:219
+#: forum/skins/default/templates/markdown_help.html:220
+#: forum/skins/default/templates/markdown_help.html:221
+#: forum/skins/zapprotect/templates/markdown_help.html:213
+#: forum/skins/zapprotect/templates/markdown_help.html:214
+#: forum/skins/zapprotect/templates/markdown_help.html:215
+#: forum/skins/zapprotect/templates/markdown_help.html:219
+#: forum/skins/zapprotect/templates/markdown_help.html:220
+#: forum/skins/zapprotect/templates/markdown_help.html:221
+msgid "Item"
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:227
+#: forum/skins/zapprotect/templates/markdown_help.html:227
+msgid ""
+"To create a bulleted list, prefix each item in the list with a star (*) "
+"character."
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:231
+#: forum/skins/default/templates/markdown_help.html:237
+#: forum/skins/zapprotect/templates/markdown_help.html:231
+#: forum/skins/zapprotect/templates/markdown_help.html:237
+msgid "A list item"
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:232
+#: forum/skins/default/templates/markdown_help.html:238
+#: forum/skins/zapprotect/templates/markdown_help.html:232
+#: forum/skins/zapprotect/templates/markdown_help.html:238
+msgid "Another list item"
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:233
+#: forum/skins/default/templates/markdown_help.html:239
+#: forum/skins/zapprotect/templates/markdown_help.html:233
+#: forum/skins/zapprotect/templates/markdown_help.html:239
+msgid "A third list item"
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:246
+#: forum/skins/zapprotect/templates/markdown_help.html:246
+msgid "A Lot More"
+msgstr ""
+
+#: forum/skins/default/templates/markdown_help.html:247
+#: forum/skins/zapprotect/templates/markdown_help.html:247
+msgid ""
+"There's a lot more to the Markdown syntax than is mentioned here.  But for "
+"creative writers, this covers a lot of the necessities.  To find out more "
+"about Markdown than you'd ever want to really know, <a href=\"http://"
+"daringfireball.net/projects/markdown/syntax\" target=\"_blank\" rel="
+"\"nofollow\">go to the Markdown page where it all started</a>."
+msgstr ""
+
+#: forum/skins/default/templates/notarobot.html:3
+#: forum/skins/zapprotect/templates/notarobot.html:3
+msgid "Please prove that you are a Human Being"
+msgstr "Моля, покажете, че сте Човек"
+
+#: forum/skins/default/templates/notarobot.html:10
+#: forum/skins/zapprotect/templates/notarobot.html:10
+msgid "I am a Human Being"
+msgstr "Аз съм Човек"
+
+#: forum/skins/default/templates/opensearch.html:4
+#: forum/skins/default/templates/opensearch.html:5
+#: forum/skins/default/templates/osqaadmin/nodeman.html:275
+#: forum/skins/zapprotect/templates/opensearch.html:4
+#: forum/skins/zapprotect/templates/opensearch.html:5
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:275
+#: rosetta/templates/rosetta/pofile.html:42
+#, fuzzy
+msgid "Search"
+msgstr "търсене"
+
+#: forum/skins/default/templates/opensearch.html:5
+#: forum/skins/zapprotect/templates/opensearch.html:5
+msgid "using your browser."
+msgstr ""
+
+#: forum/skins/default/templates/pagesize.html:6
+#: forum/skins/default/templates/paginator/page_sizes.html:4
+#: forum/skins/zapprotect/templates/pagesize.html:6
+#: forum/skins/zapprotect/templates/paginator/page_sizes.html:4
+msgid "posts per page"
+msgstr "публикации на страница"
+
+#: forum/skins/default/templates/paginator.html:6
+#: forum/skins/default/templates/paginator.html:7
+#: forum/skins/default/templates/paginator/page_numbers.html:6
+#: forum/skins/zapprotect/templates/paginator.html:6
+#: forum/skins/zapprotect/templates/paginator.html:7
+#: forum/skins/zapprotect/templates/paginator/page_numbers.html:6
+msgid "previous"
+msgstr "предишна"
+
+#: forum/skins/default/templates/paginator.html:19
+#: forum/skins/zapprotect/templates/paginator.html:19
+msgid "current page"
+msgstr "текуща страница"
+
+#: forum/skins/default/templates/paginator.html:22
+#: forum/skins/default/templates/paginator.html:29
+#: forum/skins/zapprotect/templates/paginator.html:22
+#: forum/skins/zapprotect/templates/paginator.html:29
+msgid "page number "
+msgstr "номер на страницата "
+
+#: forum/skins/default/templates/paginator.html:22
+#: forum/skins/default/templates/paginator.html:29
+#: forum/skins/zapprotect/templates/paginator.html:22
+#: forum/skins/zapprotect/templates/paginator.html:29
+msgid "number - make blank in english"
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:33
+#: forum/skins/default/templates/paginator/page_numbers.html:22
+#: forum/skins/zapprotect/templates/paginator.html:33
+#: forum/skins/zapprotect/templates/paginator/page_numbers.html:22
+msgid "next page"
+msgstr "следваща страница"
+
+#: forum/skins/default/templates/privacy.html:6
+#: forum/skins/default/templates/privacy.html:11
+#: forum/skins/zapprotect/templates/privacy.html:6
+#: forum/skins/zapprotect/templates/privacy.html:11
+msgid "Privacy policy"
+msgstr "Декларация за поверителност"
+
+#: forum/skins/default/templates/privacy.html:15
+#: forum/skins/zapprotect/templates/privacy.html:15
+msgid "general message about privacy"
+msgstr ""
+"Respecting users privacy is an important core principle of this Q&amp;A "
+"forum. Information on this page details how this forum protects your "
+"privacy, and what type of information is collected."
+
+#: forum/skins/default/templates/privacy.html:18
+#: forum/skins/zapprotect/templates/privacy.html:18
+msgid "Site Visitors"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:20
+#: forum/skins/zapprotect/templates/privacy.html:20
+msgid "what technical information is collected about visitors"
+msgstr ""
+"Information on question views, revisions of questions and answers - both "
+"times and content are recorded for each user in order to correctly count "
+"number of views, maintain data integrity and report relevant updates."
+
+#: forum/skins/default/templates/privacy.html:23
+#: forum/skins/zapprotect/templates/privacy.html:23
+msgid "Personal Information"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:25
+#: forum/skins/zapprotect/templates/privacy.html:25
+msgid "details on personal information policies"
+msgstr ""
+"Members of this community may choose to display personally identifiable "
+"information in their profiles. Forum will never display such information "
+"without a request from the user."
+
+#: forum/skins/default/templates/privacy.html:28
+#: forum/skins/zapprotect/templates/privacy.html:28
+msgid "Other Services"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:30
+#: forum/skins/zapprotect/templates/privacy.html:30
+msgid "details on sharing data with third parties"
+msgstr ""
+"None of the data that is not openly shown on the forum by the choice of the "
+"user is shared with any third party."
+
+#: forum/skins/default/templates/privacy.html:35
+#: forum/skins/zapprotect/templates/privacy.html:35
+msgid "cookie policy details"
+msgstr ""
+"Forum software relies on the internet cookie technology to keep track of "
+"user sessions. Cookies must be enabled in your browser so that forum can "
+"work for you."
+
+#: forum/skins/default/templates/privacy.html:37
+#: forum/skins/zapprotect/templates/privacy.html:37
+msgid "Policy Changes"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:38
+#: forum/skins/zapprotect/templates/privacy.html:38
+msgid "how privacy policies can be changed"
+msgstr ""
+"These policies may be adjusted to improve protection of user's privacy. "
+"Whenever such changes occur, users will be notified via the internal "
+"messaging system. "
+
+#: forum/skins/default/templates/question.html:110
+#: forum/skins/default/templates/sidebar/recent_tags.html:9
+#: forum/skins/zapprotect/templates/question.html:110
+#: forum/skins/zapprotect/templates/sidebar/recent_tags.html:9
+#, python-format
+msgid "see questions tagged '%(tagname)s'"
+msgstr "още въпроси с таг '%(tagname)s'"
+
+#: forum/skins/default/templates/question.html:129
+#: forum/skins/zapprotect/templates/question.html:129
+#, python-format
+msgid ""
+"The question has been closed for the following reason \"%(close_reason)s\" by"
+msgstr "Въпроса беше затворен поради \"%(close_reason)s\" от"
+
+#: forum/skins/default/templates/question.html:140
+#: forum/skins/zapprotect/templates/question.html:140
+#, fuzzy, python-format
+msgid "One Answer:"
+msgid_plural "%(counter)s Answers:"
+msgstr[0] "най-новите"
+msgstr[1] "най-новите"
+
+#: forum/skins/default/templates/question.html:189
+#: forum/skins/zapprotect/templates/question.html:189
+msgid "Your answer"
+msgstr "Вашия отговор"
+
+#: forum/skins/default/templates/question.html:191
+#: forum/skins/zapprotect/templates/question.html:191
+msgid "Be the first one to answer this question!"
+msgstr "Бъдете първия отговорил на този въпрос!"
+
+#: forum/skins/default/templates/question.html:198
+#: forum/skins/zapprotect/templates/question.html:198
+#, fuzzy
+msgid "You can answer anonymously and then login."
+msgstr ""
+"<span class='strong big'>Започнете да добавяте анонимно</span> - Вашия "
+"отговор ще бъда запазен в сесията докато влезнете или си направите акаунт. "
+"Моля използвайте <strong>неутрални отговори</strong>, за дискусия, "
+"<strong>използвайте само коментарите</strong> и <strong>моля, гласувайте</"
+"strong> (след като се оторизирате)!"
+
+#: forum/skins/default/templates/question.html:202
+#: forum/skins/zapprotect/templates/question.html:202
+#, fuzzy
+msgid "Answer your own question only to give an answer."
+msgstr ""
+"<span class='big strong'>Вие можете да отговорите на Вашия въпрос</span>, но "
+"се уверете че предоставяте <strong>отговор</strong>. Запомнете, че винаги "
+"можете <strong>да промените първоначалния въпрос</strong>. Моля "
+"<strong>използвайте коментари за дискутиране</strong> и <strong>не "
+"забравяйте да гласувате</strong> за отговорите, които харесвате (или не "
+"харесвате)"
+
+#: forum/skins/default/templates/question.html:204
+#: forum/skins/zapprotect/templates/question.html:204
+#, fuzzy
+msgid "Please only give an answer, no discussions."
+msgstr ""
+"<span class='big strong'>Отговора трябва да съдържа само съществена "
+"информация</span>. Ако искате да коментирате, просто <strong>използвайте "
+"опцията за коментиране</strong>. Запомнете, че винаги можете да "
+"<strong>промените Вашите отговори</strong> - не е нужно да отговаряте на "
+"същите въпроси два пъти. Защо така <strong>не забравяйте да гласувате</"
+"strong> - наистина помага да бъдат избрани най-добрите въпроси и отговори!"
+
+#: forum/skins/default/templates/question.html:207
+#: forum/skins/zapprotect/templates/question.html:207
+msgid ""
+"Remember, your answer will not be published until you validate your email."
+msgstr ""
+
+#: forum/skins/default/templates/question.html:246
+#: forum/skins/zapprotect/templates/question.html:246
+msgid "Login/Signup to Post Your Answer"
+msgstr "Оторизирайте се за да добавите Вашия отговор"
+
+#: forum/skins/default/templates/question.html:249
+#: forum/skins/zapprotect/templates/question.html:249
+msgid "Answer Your Own Question"
+msgstr "Отговорете на Вашия въпрос"
+
+#: forum/skins/default/templates/question.html:251
+#: forum/skins/zapprotect/templates/question.html:251
+msgid "Answer the question"
+msgstr "Изпратете Вашия отговор"
+
+#: forum/skins/default/templates/question.html:269
+#: forum/skins/zapprotect/templates/question.html:269
+msgid "Question tags"
+msgstr "Тагове"
+
+#: forum/skins/default/templates/question.html:274
+#: forum/skins/default/templates/question_summary_list_roll.html:52
+#: forum/skins/default/templates/tags.html:45
+#: forum/skins/default/templates/question_list/item.html:31
+#: forum/skins/zapprotect/templates/question.html:274
+#: forum/skins/zapprotect/templates/question_summary_list_roll.html:52
+#: forum/skins/zapprotect/templates/tags.html:45
+#: forum/skins/zapprotect/templates/question_list/item.html:31
+msgid "see questions tagged"
+msgstr "виж въпросите по тагове"
+
+#: forum/skins/default/templates/question.html:274
+#: forum/skins/default/templates/question_summary_list_roll.html:52
+#: forum/skins/default/templates/tags.html:45
+#: forum/skins/default/templates/question_list/item.html:31
+#: forum/skins/zapprotect/templates/question.html:274
+#: forum/skins/zapprotect/templates/question_summary_list_roll.html:52
+#: forum/skins/zapprotect/templates/tags.html:45
+#: forum/skins/zapprotect/templates/question_list/item.html:31
+msgid "using tags"
+msgstr "използва тагове"
+
+#: forum/skins/default/templates/question.html:279
+#: forum/skins/zapprotect/templates/question.html:279
+msgid "question asked"
+msgstr "Зададен въпрос"
+
+#: forum/skins/default/templates/question.html:282
+#: forum/skins/zapprotect/templates/question.html:282
+msgid "question was seen"
+msgstr "Въпроса е видян"
+
+#: forum/skins/default/templates/question.html:282
+#: forum/skins/zapprotect/templates/question.html:282
+msgid "times"
+msgstr "пъти"
+
+#: forum/skins/default/templates/question.html:285
+#: forum/skins/zapprotect/templates/question.html:285
+msgid "last updated"
+msgstr "Последно обновен"
+
+#: forum/skins/default/templates/question.html:291
+#: forum/skins/zapprotect/templates/question.html:291
+msgid "Related questions"
+msgstr "Подобни въпроси"
+
+#: forum/skins/default/templates/question_edit.html:5
+#: forum/skins/default/templates/question_edit.html:91
+#: forum/skins/zapprotect/templates/question_edit.html:5
+#: forum/skins/zapprotect/templates/question_edit.html:91
+msgid "Edit question"
+msgstr "Редактирай въпроса"
+
+#: forum/skins/default/templates/question_edit_tips.html:4
+#: forum/skins/zapprotect/templates/question_edit_tips.html:4
+msgid "Title Tips"
+msgstr ""
+
+#: forum/skins/default/templates/question_edit_tips.html:9
+#: forum/skins/zapprotect/templates/question_edit_tips.html:9
+#, fuzzy, python-format
+msgid ""
+"\n"
+"                ask a question relevant to the %(app_title)s community \n"
+"                "
+msgstr ""
+"\n"
+"(one comment)"
+
+#: forum/skins/default/templates/question_edit_tips.html:15
+#: forum/skins/zapprotect/templates/question_edit_tips.html:15
+msgid "please try provide enough details"
+msgstr "уверете се, че уточнявате всички аспекти"
+
+#: forum/skins/default/templates/question_edit_tips.html:30
+#: forum/skins/zapprotect/templates/question_edit_tips.html:30
+msgid "What Are Tags"
+msgstr ""
+
+#: forum/skins/default/templates/question_edit_tips.html:33
+#: forum/skins/zapprotect/templates/question_edit_tips.html:33
+msgid "Tags are words that will tell others what this question is about."
+msgstr ""
+
+#: forum/skins/default/templates/question_edit_tips.html:36
+#: forum/skins/zapprotect/templates/question_edit_tips.html:36
+msgid "They will help other find your question."
+msgstr ""
+
+#: forum/skins/default/templates/question_edit_tips.html:39
+#: forum/skins/zapprotect/templates/question_edit_tips.html:39
+#, python-format
+msgid ""
+"\n"
+"                A question can have up to %(max_number_of_tags)s tags, but "
+"it must have at least %(min_number_of_tags)s.\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:5
+#: forum/skins/default/templates/question_retag.html:58
+#: forum/skins/zapprotect/templates/question_retag.html:5
+#: forum/skins/zapprotect/templates/question_retag.html:58
+msgid "Change tags"
+msgstr "Промени таговете"
+
+#: forum/skins/default/templates/question_retag.html:43
+#: forum/skins/zapprotect/templates/question_retag.html:43
+msgid "tags are required"
+msgstr "таговете са задължителни"
+
+#: forum/skins/default/templates/question_retag.html:44
+#: forum/skins/zapprotect/templates/question_retag.html:44
+#, fuzzy, python-format
+msgid ""
+"\n"
+"                        maxlength: \"up to %(max_number_of_tags)s tags, less "
+"than %(max_length_of_tags)s characters each\"\n"
+"                        "
+msgstr ""
+"\n"
+"<div class=\"questions-count\">%(q_num)s</div><p>question with title "
+"containing <strong><span class=\"darkred\">%(searchtitle)s</span></strong></"
+"p>"
+
+#: forum/skins/default/templates/question_retag.html:88
+#: forum/skins/zapprotect/templates/question_retag.html:88
+msgid "Why use and modify tags?"
+msgstr "Защо да използваме тагове?"
+
+#: forum/skins/default/templates/question_retag.html:91
+#: forum/skins/zapprotect/templates/question_retag.html:91
+msgid "tags help us keep Questions organized"
+msgstr "таговете ни помагат да организираме въпросите"
+
+#: forum/skins/default/templates/question_retag.html:99
+#: forum/skins/zapprotect/templates/question_retag.html:99
+msgid "tag editors receive special awards from the community"
+msgstr "редакторите на тагове получават специални награди от общността"
+
+#: forum/skins/default/templates/question_summary_list_roll.html:13
+#: forum/skins/default/templates/question_list/count.html:15
+#: forum/skins/default/templates/question_list/item.html:15
+#: forum/skins/zapprotect/templates/question_summary_list_roll.html:13
+#: forum/skins/zapprotect/templates/question_list/count.html:15
+#: forum/skins/zapprotect/templates/question_list/item.html:15
+#: forum/views/users.py:55
+msgid "answers"
+msgstr "отговори"
+
+#: forum/skins/default/templates/question_summary_list_roll.html:14
+#: forum/skins/default/templates/question_list/item.html:11
+#: forum/skins/zapprotect/templates/question_summary_list_roll.html:14
+#: forum/skins/zapprotect/templates/question_list/item.html:11
+#: forum/views/commands.py:77 forum/views/readers.py:62
+#: forum/views/readers.py:63 forum/views/readers.py:265
+#: forum/views/users.py:54 forum/views/users.py:55 forum/views/users.py:356
+msgid "votes"
+msgstr "гласове"
+
+#: forum/skins/default/templates/question_summary_list_roll.html:15
+#: forum/skins/default/templates/question_list/item.html:19
+#: forum/skins/zapprotect/templates/question_summary_list_roll.html:15
+#: forum/skins/zapprotect/templates/question_list/item.html:19
+msgid "views"
+msgstr "преглеждания"
+
+#: forum/skins/default/templates/questions.html:18
+#: forum/skins/default/templates/users/stats.html:19
+#: forum/skins/zapprotect/templates/questions.html:18
+#: forum/skins/zapprotect/templates/users/stats.html:19
+#, fuzzy
+msgid "subscribe to question RSS feed"
+msgstr "Вие сте абониран за този въпрос."
+
+#: forum/skins/default/templates/reopen.html:6
+#: forum/skins/default/templates/reopen.html:16
+#: forum/skins/zapprotect/templates/reopen.html:6
+#: forum/skins/zapprotect/templates/reopen.html:16
+msgid "Reopen question"
+msgstr "Отвори отново въпроса"
+
+#: forum/skins/default/templates/reopen.html:19
+#: forum/skins/zapprotect/templates/reopen.html:19
+msgid "Open the previously closed question"
+msgstr "Отвори преди затворения въпрос"
+
+#: forum/skins/default/templates/reopen.html:22
+#: forum/skins/zapprotect/templates/reopen.html:22
+msgid "The question was closed for the following reason "
+msgstr "Въпроса е бил затворен поради следната причина "
+
+#: forum/skins/default/templates/reopen.html:22
+#: forum/skins/zapprotect/templates/reopen.html:22
+msgid "reason - leave blank in english"
+msgstr "причина - остави празно"
+
+#: forum/skins/default/templates/reopen.html:22
+#: forum/skins/zapprotect/templates/reopen.html:22
+msgid "on "
+msgstr "на "
+
+#: forum/skins/default/templates/reopen.html:22
+#: forum/skins/zapprotect/templates/reopen.html:22
+msgid "date closed"
+msgstr "дата на затваряне"
+
+#: forum/skins/default/templates/reopen.html:29
+#: forum/skins/zapprotect/templates/reopen.html:29
+msgid "Reopen this question"
+msgstr "Отвори отново този въпрос"
+
+#: forum/skins/default/templates/revisions.html:7
+#: forum/skins/default/templates/revisions.html:38
+#: forum/skins/zapprotect/templates/revisions.html:7
+#: forum/skins/zapprotect/templates/revisions.html:38
+msgid "Revision history"
+msgstr "История на ревизиите"
+
+#: forum/skins/default/templates/revisions.html:52
+#: forum/skins/zapprotect/templates/revisions.html:52
+msgid "click to hide/show revision"
+msgstr "скрий/покажи ревизиите"
+
+#: forum/skins/default/templates/search.html:7
+#: forum/skins/zapprotect/templates/search.html:7
+#, python-format
+msgid ""
+"\n"
+"\t    Search in %(app_name)s\n"
+"\t"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:3
+#: forum/skins/zapprotect/templates/subscription_status.html:3
+#, fuzzy
+msgid "Follow this question"
+msgstr "Отвори отново този въпрос"
+
+#: forum/skins/default/templates/subscription_status.html:4
+#: forum/skins/zapprotect/templates/subscription_status.html:4
+#, fuzzy
+msgid "By Email"
+msgstr ""
+"<strong>Your Email</strong> (<i>must be valid, never shown to others</i>)"
+
+#: forum/skins/default/templates/subscription_status.html:9
+#: forum/skins/zapprotect/templates/subscription_status.html:9
+msgid "You were automatically subscribed to this question."
+msgstr "Вие бяхте автоматично абониран за този въпрос."
+
+#: forum/skins/default/templates/subscription_status.html:11
+#: forum/skins/zapprotect/templates/subscription_status.html:11
+msgid "You are subscribed to this question."
+msgstr "Вие сте абониран за този въпрос."
+
+#: forum/skins/default/templates/subscription_status.html:14
+#: forum/skins/zapprotect/templates/subscription_status.html:14
+msgid "You are not subscribed to this question."
+msgstr "Вие не сте абониран за този въпрос."
+
+#: forum/skins/default/templates/subscription_status.html:19
+#: forum/skins/zapprotect/templates/subscription_status.html:19
+#: forum/views/commands.py:463
+msgid "unsubscribe me"
+msgstr "махни абонамента ми"
+
+#: forum/skins/default/templates/subscription_status.html:21
+#: forum/skins/zapprotect/templates/subscription_status.html:21
+#: forum/views/commands.py:463
+msgid "subscribe me"
+msgstr "абонирай ме"
+
+#: forum/skins/default/templates/subscription_status.html:26
+#: forum/skins/zapprotect/templates/subscription_status.html:26
+#, fuzzy, python-format
+msgid ""
+"\n"
+"            (you can adjust your notification settings on your <a href=\"%"
+"(subscriptions_url)s\">profile</a>)\n"
+"        "
+msgstr ""
+"(можете да промените абонаментните настройки в Вашия <a href=\"%(profile_url)"
+"s?sort=email_subscriptions\">профил</a>)\n"
+
+#: forum/skins/default/templates/subscription_status.html:31
+#: forum/skins/zapprotect/templates/subscription_status.html:31
+#, fuzzy
+msgid "Once you sign in you will be able to subscribe for any updates here"
+msgstr ""
+"<span class='strong'>Тук</span> (след като се оторизирате) ще можете да се "
+"абонирате за периодични известявания по този въпрос."
+
+#: forum/skins/default/templates/subscription_status.html:33
+#: forum/skins/zapprotect/templates/subscription_status.html:33
+msgid "By RSS"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:36
+#: forum/skins/zapprotect/templates/subscription_status.html:36
+#, fuzzy
+msgid "subscribe to answers"
+msgstr "абонирай ме"
+
+#: forum/skins/default/templates/subscription_status.html:37
+#: forum/skins/zapprotect/templates/subscription_status.html:37
+#, fuzzy
+msgid "Answers"
+msgstr "отговори"
+
+#: forum/skins/default/templates/subscription_status.html:41
+#: forum/skins/zapprotect/templates/subscription_status.html:41
+#, fuzzy
+msgid "subscribe to comments and answers"
+msgstr "най-старите"
+
+#: forum/skins/default/templates/subscription_status.html:42
+#: forum/skins/zapprotect/templates/subscription_status.html:42
+#, fuzzy
+msgid "Answers and Comments"
+msgstr "добави коментари"
+
+#: forum/skins/default/templates/tag_selector.html:4
+#: forum/skins/default/templates/question_list/tag_selector.html:6
+#: forum/skins/zapprotect/templates/tag_selector.html:4
+#: forum/skins/zapprotect/templates/question_list/tag_selector.html:6
+msgid "Interesting tags"
+msgstr "Интересни тагове"
+
+#: forum/skins/default/templates/tag_selector.html:10
+#: forum/skins/default/templates/tag_selector.html:27
+#: forum/skins/default/templates/question_list/related_tags.html:9
+#: forum/skins/default/templates/question_list/tag_selector.html:12
+#: forum/skins/default/templates/question_list/tag_selector.html:29
+#: forum/skins/zapprotect/templates/tag_selector.html:10
+#: forum/skins/zapprotect/templates/tag_selector.html:27
+#: forum/skins/zapprotect/templates/question_list/related_tags.html:9
+#: forum/skins/zapprotect/templates/question_list/tag_selector.html:12
+#: forum/skins/zapprotect/templates/question_list/tag_selector.html:29
+#, python-format
+msgid "see questions tagged '%(tag_name)s'"
+msgstr "виж въпросите с таг '%(tag_name)s'"
+
+#: forum/skins/default/templates/tag_selector.html:14
+#: forum/skins/default/templates/question_list/tag_selector.html:16
+#: forum/skins/zapprotect/templates/tag_selector.html:14
+#: forum/skins/zapprotect/templates/question_list/tag_selector.html:16
+#, python-format
+msgid "remove '%(tag_name)s' from the list of interesting tags"
+msgstr "премахни '%(tag_name)s' от списъка с интересни тагове"
+
+#: forum/skins/default/templates/tag_selector.html:20
+#: forum/skins/default/templates/tag_selector.html:37
+#: forum/skins/default/templates/question_list/tag_selector.html:22
+#: forum/skins/default/templates/question_list/tag_selector.html:39
+#: forum/skins/zapprotect/templates/tag_selector.html:20
+#: forum/skins/zapprotect/templates/tag_selector.html:37
+#: forum/skins/zapprotect/templates/question_list/tag_selector.html:22
+#: forum/skins/zapprotect/templates/question_list/tag_selector.html:39
+msgid "Add"
+msgstr "Добави"
+
+#: forum/skins/default/templates/tag_selector.html:21
+#: forum/skins/default/templates/question_list/tag_selector.html:23
+#: forum/skins/zapprotect/templates/tag_selector.html:21
+#: forum/skins/zapprotect/templates/question_list/tag_selector.html:23
+msgid "Ignored tags"
+msgstr "Игнорирани тагове"
+
+#: forum/skins/default/templates/tag_selector.html:31
+#: forum/skins/default/templates/question_list/tag_selector.html:33
+#: forum/skins/zapprotect/templates/tag_selector.html:31
+#: forum/skins/zapprotect/templates/question_list/tag_selector.html:33
+#, python-format
+msgid "remove '%(tag_name)s' from the list of ignored tags"
+msgstr "премахни '%(tag_name)s' от списъка с игнорирани тагове"
+
+#: forum/skins/default/templates/tag_selector.html:40
+#: forum/skins/default/templates/question_list/tag_selector.html:43
+#: forum/skins/zapprotect/templates/tag_selector.html:40
+#: forum/skins/zapprotect/templates/question_list/tag_selector.html:43
+msgid "keep ignored questions hidden"
+msgstr "скривай игнорираните въпроси"
+
+#: forum/skins/default/templates/tags.html:6
+#: forum/skins/default/templates/tags.html:29
+#: forum/skins/zapprotect/templates/tags.html:6
+#: forum/skins/zapprotect/templates/tags.html:29
+msgid "Tag list"
+msgstr "Списък тагове"
+
+#: forum/skins/default/templates/tags.html:35
+#: forum/skins/zapprotect/templates/tags.html:35
+msgid "All tags matching query"
+msgstr "Всички тагове отговарящи на заявката"
+
+#: forum/skins/default/templates/tags.html:38
+#: forum/skins/zapprotect/templates/tags.html:38
+msgid "Nothing found"
+msgstr "Нищо не беше намерено"
+
+#: forum/skins/default/templates/auth/auth_settings.html:5
+#: forum/skins/default/templates/auth/auth_settings.html:7
+#: forum/skins/zapprotect/templates/auth/auth_settings.html:5
+#: forum/skins/zapprotect/templates/auth/auth_settings.html:7
+msgid "Authentication settings"
+msgstr "Опции за оторизиране"
+
+#: forum/skins/default/templates/auth/auth_settings.html:9
+#: forum/skins/zapprotect/templates/auth/auth_settings.html:9
+msgid ""
+"These are the external authentication providers currently associated with "
+"your account."
+msgstr "Това са външни оторизатори свързани с Вашия акаунт"
+
+#: forum/skins/default/templates/auth/auth_settings.html:17
+#: forum/skins/zapprotect/templates/auth/auth_settings.html:17
+msgid ""
+"You currently have no external authentication provider associated with your "
+"account."
+msgstr "В момента нямате външни оторизатори свързани с Вашия акаунт."
+
+#: forum/skins/default/templates/auth/auth_settings.html:20
+#: forum/skins/zapprotect/templates/auth/auth_settings.html:20
+msgid "Add new provider"
+msgstr "Добави нов оторизатор"
+
+#: forum/skins/default/templates/auth/auth_settings.html:24
+#: forum/skins/zapprotect/templates/auth/auth_settings.html:24
+msgid "This is where you can change your password. Make sure you remember it!"
+msgstr ""
+"<span class='strong'>За да промените паролата</span> попълнете и изпратете "
+"формата."
+
+#: forum/skins/default/templates/auth/auth_settings.html:26
+#: forum/skins/zapprotect/templates/auth/auth_settings.html:26
+msgid ""
+"You can set up a password for your account, so you can login using standard "
+"username and password!"
+msgstr ""
+"Можете да зададете парола за Вашия акаунт, така че да използвате стандартно "
+"потребителско име и парола!"
+
+#: forum/skins/default/templates/auth/auth_settings.html:33
+#: forum/skins/zapprotect/templates/auth/auth_settings.html:33
+#, fuzzy
+msgid "Create password"
+msgstr "Парола <i>(напишете отново)</i>"
+
+#: forum/skins/default/templates/auth/complete.html:5
+#: forum/skins/zapprotect/templates/auth/complete.html:5
+msgid "Connect your OpenID with this site"
+msgstr "Свържете OpenID към този сайт"
+
+#: forum/skins/default/templates/auth/complete.html:8
+#: forum/skins/zapprotect/templates/auth/complete.html:8
+msgid "Connect your OpenID with your account on this site"
+msgstr "Нова потребителска регистрация"
+
+#: forum/skins/default/templates/auth/complete.html:12
+#: forum/skins/zapprotect/templates/auth/complete.html:12
+msgid "You are here for the first time with "
+msgstr "Вие сте тук за пръв път от "
+
+#: forum/skins/default/templates/auth/complete.html:13
+#: forum/skins/zapprotect/templates/auth/complete.html:13
+msgid ""
+"Please create your screen name and save your email address. Saved email "
+"address will let you subscribe for the updates on the most interesting "
+"questions and will be used to create and retrieve your unique avatar image. "
+msgstr ""
+"Създайте Вашето публично име и запазете имейла си. Запазените имейл адреси "
+"ще можете да използвате за да се абонирате за известия за най-интересните "
+"въпроси."
+
+#: forum/skins/default/templates/auth/complete.html:15
+#: forum/skins/zapprotect/templates/auth/complete.html:15
+msgid "This account already exists, please use another."
+msgstr "Този акаунт вече съществува, изплозвайте друг."
+
+#: forum/skins/default/templates/auth/complete.html:70
+#: forum/skins/zapprotect/templates/auth/complete.html:70
+msgid "receive updates motivational blurb"
+msgstr ""
+"<strong>Получавайте ъпдейти по имейл</strong> - това ще помогне на нашата "
+"общност да помогне и да стане по-ползотворна.<br/>По подразбиране, се "
+"изпраща само един имейл на седмица с цялата най-важна информация.<br/>Ако "
+"желаете, можете да промените тази опция сега или по всяко едно време през "
+"настройките на Вашия акаунт."
+
+#: forum/skins/default/templates/auth/complete.html:74
+#: forum/skins/zapprotect/templates/auth/complete.html:74
+msgid "please select one of the options above"
+msgstr "изберете една от посочените опции"
+
+#: forum/skins/default/templates/auth/complete.html:77
+#: forum/skins/zapprotect/templates/auth/complete.html:77
+msgid "Tag filter tool will be your right panel, once you log in."
+msgstr "Инстромент за филтриране на тагове, намира се отдясно след оторизация."
+
+#: forum/skins/default/templates/auth/complete.html:78
+#: forum/skins/zapprotect/templates/auth/complete.html:78
+msgid "create account"
+msgstr "Регистрация"
+
+#: forum/skins/default/templates/auth/complete.html:87
+#: forum/skins/zapprotect/templates/auth/complete.html:87
+msgid "Existing account"
+msgstr "Съществуващ акаунт"
+
+#: forum/skins/default/templates/auth/complete.html:88
+#: forum/skins/zapprotect/templates/auth/complete.html:88
+msgid "user name"
+msgstr "потребителско име"
+
+#: forum/skins/default/templates/auth/complete.html:89
+#: forum/skins/zapprotect/templates/auth/complete.html:89
+msgid "password"
+msgstr "парола"
+
+#: forum/skins/default/templates/auth/complete.html:96
+#: forum/skins/zapprotect/templates/auth/complete.html:96
+msgid "Register"
+msgstr "Регистрация"
+
+#: forum/skins/default/templates/auth/complete.html:97
+#: forum/skins/zapprotect/templates/auth/complete.html:97
+#: forum_modules/localauth/templates/loginform.html:27
+msgid "Forgot your password?"
+msgstr "Забравена парола?"
+
+#: forum/skins/default/templates/auth/mail_validation.html:11
+#: forum/skins/zapprotect/templates/auth/mail_validation.html:11
+#, python-format
+msgid "%(prefix)s Your email validation link %(app_name)s"
+msgstr ""
+
+#: forum/skins/default/templates/auth/mail_validation.html:14
+#: forum/skins/zapprotect/templates/auth/mail_validation.html:14
+#, fuzzy
+msgid "Please use the following link to help us verify your email address:"
+msgstr "Използването на посочения линк ще потвърди Вашия имейл."
+
+#: forum/skins/default/templates/auth/mail_validation.html:16
+#: forum/skins/default/templates/auth/welcome_email.html:26
+#: forum/skins/zapprotect/templates/auth/mail_validation.html:16
+#: forum/skins/zapprotect/templates/auth/welcome_email.html:26
+#, fuzzy
+msgid "Validate my email address"
+msgstr "Your email <i>(never shared)</i>"
+
+#: forum/skins/default/templates/auth/mail_validation.html:18
+#: forum/skins/default/templates/auth/temp_login_email.html:19
+#: forum/skins/default/templates/auth/welcome_email.html:28
+#: forum/skins/zapprotect/templates/auth/mail_validation.html:18
+#: forum/skins/zapprotect/templates/auth/temp_login_email.html:19
+#: forum/skins/zapprotect/templates/auth/welcome_email.html:28
+msgid ""
+"If the above link is not clickable, copy and paste this url into your web "
+"browser's address bar:"
+msgstr ""
+
+#: forum/skins/default/templates/auth/mail_validation.html:24
+#: forum/skins/default/templates/auth/welcome_email.html:40
+#: forum/skins/zapprotect/templates/auth/mail_validation.html:24
+#: forum/skins/zapprotect/templates/auth/welcome_email.html:40
+msgid ""
+"Copy and paste this url into your web browser's address bar to help us "
+"verify your email address:"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:6
+#: forum/skins/zapprotect/templates/auth/signin.html:6
+#: forum_modules/localauth/templates/loginform.html:24
+#: forum_modules/openidauth/templates/openidurl.html:15
+msgid "Login"
+msgstr "Вход"
+
+#: forum/skins/default/templates/auth/signin.html:24
+#: forum/skins/zapprotect/templates/auth/signin.html:24
+msgid "User login"
+msgstr "Потребителски вход"
+
+#: forum/skins/default/templates/auth/signin.html:36
+#: forum/skins/default/templates/auth/signin.html:93
+#: forum/skins/default/templates/auth/signin.html:99
+#: forum/skins/zapprotect/templates/auth/signin.html:36
+#: forum/skins/zapprotect/templates/auth/signin.html:93
+#: forum/skins/zapprotect/templates/auth/signin.html:99
+msgid "Or..."
+msgstr "Или..."
+
+#: forum/skins/default/templates/auth/signin.html:39
+#: forum/skins/zapprotect/templates/auth/signin.html:39
+msgid ""
+"\n"
+"        External login services use <b><a href=\"http://openid.net/"
+"\">OpenID</a></b> technology, where your password always stays confidential "
+"between\n"
+"        you and your login provider and you don't have to remember another "
+"one.\n"
+"    "
+msgstr ""
+"\n"
+"Външните услуги за оторизация използват <b><a href=\"http://openid.net/"
+"\">OpenID</a></b> технология, като цялата информация между клиента и сървъра "
+"остава защитена.     "
+
+#: forum/skins/default/templates/auth/signin.html:47
+#: forum/skins/zapprotect/templates/auth/signin.html:47
+msgid "Validate my email after I login."
+msgstr "Потвърди моя имейл след като влезна."
+
+#: forum/skins/default/templates/auth/signin.html:102
+#: forum/skins/zapprotect/templates/auth/signin.html:102
+msgid "Click"
+msgstr "Кликнете"
+
+#: forum/skins/default/templates/auth/signin.html:102
+#: forum/skins/zapprotect/templates/auth/signin.html:102
+msgid "if you're having troubles signing in."
+msgstr "ако имате проблем с влизането."
+
+#: forum/skins/default/templates/auth/signin.html:107
+#: forum/skins/zapprotect/templates/auth/signin.html:107
+msgid "Enter your "
+msgstr "Въведете Вашия "
+
+#: forum/skins/default/templates/auth/signin.html:163
+#: forum/skins/zapprotect/templates/auth/signin.html:163
+msgid "Why use OpenID?"
+msgstr "Защо да използваме OpenID?"
+
+#: forum/skins/default/templates/auth/signin.html:166
+#: forum/skins/zapprotect/templates/auth/signin.html:166
+msgid "with openid it is easier"
+msgstr "Използвайки OpenID не е нужно да създавате нов потребител."
+
+#: forum/skins/default/templates/auth/signin.html:169
+#: forum/skins/zapprotect/templates/auth/signin.html:169
+msgid "reuse openid"
+msgstr ""
+"Можете спокойно да използвате същия OpenID профил за останалите сайтове, "
+"поддържащи технологията."
+
+#: forum/skins/default/templates/auth/signin.html:172
+#: forum/skins/zapprotect/templates/auth/signin.html:172
+msgid "openid is widely adopted"
+msgstr ""
+"Има повече от 200 000 000 OpenID профила и повече от 15 000 сайта поддържащи "
+"технологията."
+
+#: forum/skins/default/templates/auth/signin.html:175
+#: forum/skins/zapprotect/templates/auth/signin.html:175
+msgid "openid is supported open standard"
+msgstr "OpenID е базиран на отворен стандарт, поддържан от много компании."
+
+#: forum/skins/default/templates/auth/signin.html:180
+#: forum/skins/zapprotect/templates/auth/signin.html:180
+msgid "Find out more"
+msgstr "Разбери повече"
+
+#: forum/skins/default/templates/auth/signin.html:181
+#: forum/skins/zapprotect/templates/auth/signin.html:181
+msgid "Get OpenID"
+msgstr "Вземи OpenID"
+
+#: forum/skins/default/templates/auth/temp_login_email.html:11
+#: forum/skins/zapprotect/templates/auth/temp_login_email.html:11
+#, python-format
+msgid "%(prefix)s Temporary login link"
+msgstr "%(prefix)s Временен линк за вход"
+
+#: forum/skins/default/templates/auth/temp_login_email.html:15
+#: forum/skins/zapprotect/templates/auth/temp_login_email.html:15
+#, python-format
+msgid ""
+"The following link grants you a one time access to your account at %"
+"(app_name)s."
+msgstr ""
+"Следния линк предоставя възможност за еднократна оторизация на %(app_name)s"
+
+#: forum/skins/default/templates/auth/temp_login_email.html:17
+#: forum/skins/zapprotect/templates/auth/temp_login_email.html:17
+#, fuzzy
+msgid "Go to your account"
+msgstr ""
+"<strong>Нов имейл:</strong> (няма да бъде споделян, трябва да бъде "
+"действителен)"
+
+#: forum/skins/default/templates/auth/temp_login_email.html:25
+#: forum/skins/zapprotect/templates/auth/temp_login_email.html:25
+#, python-format
+msgid ""
+"The following url grants you a one time access to your account at %(app_name)"
+"s."
+msgstr ""
+"Следния адрес предоставя права за еднократна оторизация във Вашия профил на %"
+"(app_name)s"
+
+#: forum/skins/default/templates/auth/temp_login_request.html:5
+#: forum/skins/zapprotect/templates/auth/temp_login_request.html:5
+msgid "Request temporary login key"
+msgstr "Поискай временен ключ за достъп"
+
+#: forum/skins/default/templates/auth/temp_login_request.html:7
+#: forum/skins/zapprotect/templates/auth/temp_login_request.html:7
+msgid "Account: request temporary login key"
+msgstr "Профил: поискай временен ключ за достъп"
+
+#: forum/skins/default/templates/auth/temp_login_request.html:8
+#: forum/skins/zapprotect/templates/auth/temp_login_request.html:8
+#, fuzzy
+msgid ""
+"\n"
+"    If you're experiencing problems accessing your account, or if you forgot "
+"your password,\n"
+"    here you can request a temporary login key. Fill out your account email "
+"and we'll send you a temporary access link that\n"
+"    will enable you to access your account. This token is valid only once "
+"and for a limited period of time.\n"
+" "
+msgstr ""
+"Ако изпитвате проблеми с достъпа до Вашия акаунт или сте забравили паролата "
+"си, тук можете да поискате временен код за достъп. Попълнете Вашия имейл "
+"адрес и ние ще изпратим временна връзка, предоставяща достъп до профила. "
+"Това ще Ви даде шанс да получите достъп до профила си. Този код е достъпен "
+"само веднъж и за определен интервал от време.\n"
+
+#: forum/skins/default/templates/auth/temp_login_request.html:25
+#: forum/skins/zapprotect/templates/auth/temp_login_request.html:25
+#, fuzzy
+msgid "Send link"
+msgstr "Изпрати връзка"
+
+#: forum/skins/default/templates/auth/welcome_email.html:12
+#: forum/skins/zapprotect/templates/auth/welcome_email.html:12
+#, fuzzy, python-format
+msgid "%(prefix)s Welcome to %(app_name)s"
+msgstr "%(username)s е нов потребител на %(app_name)s"
+
+#: forum/skins/default/templates/auth/welcome_email.html:16
+#: forum/skins/default/templates/auth/welcome_email.html:34
+#: forum/skins/zapprotect/templates/auth/welcome_email.html:16
+#: forum/skins/zapprotect/templates/auth/welcome_email.html:34
+#, python-format
+msgid ""
+"Howdy and welcome to %(app_name)s. We know you're busy, so we'll keep this "
+"real simple."
+msgstr ""
+"Добре дошли на %(app_name)s. Знаем, че сте заети, за това обещаваме всичко "
+"да бъде максимално просто."
+
+#: forum/skins/default/templates/auth/welcome_email.html:19
+#: forum/skins/default/templates/auth/welcome_email.html:35
+#: forum/skins/zapprotect/templates/auth/welcome_email.html:19
+#: forum/skins/zapprotect/templates/auth/welcome_email.html:35
+msgid "Here's your login info (store it in a cool dry place):"
+msgstr "Това е Вашата информация за логин (запазете я на сигурно място):"
+
+#: forum/skins/default/templates/auth/welcome_email.html:21
+#: forum/skins/default/templates/auth/welcome_email.html:37
+#: forum/skins/zapprotect/templates/auth/welcome_email.html:21
+#: forum/skins/zapprotect/templates/auth/welcome_email.html:37
+#, fuzzy
+msgid "Username: "
+msgstr "Потребителско име: "
+
+#: forum/skins/default/templates/auth/welcome_email.html:22
+#: forum/skins/default/templates/auth/welcome_email.html:38
+#: forum/skins/zapprotect/templates/auth/welcome_email.html:22
+#: forum/skins/zapprotect/templates/auth/welcome_email.html:38
+msgid "Password: As IF we would send your password in cleartext!"
+msgstr "Парола: "
+
+#: forum/skins/default/templates/auth/welcome_email.html:24
+#: forum/skins/zapprotect/templates/auth/welcome_email.html:24
+#, fuzzy
+msgid "The following link will help us verify your email address:"
+msgstr "Използването на посочения линк ще потвърди Вашия имейл."
+
+#: forum/skins/default/templates/feeds/rss_answer_title.html:2
+#: forum/skins/zapprotect/templates/feeds/rss_answer_title.html:2
+#, python-format
+msgid "Answer by %(author)s"
+msgstr "Отговор от %(author)s"
+
+#: forum/skins/default/templates/node/accept_button.html:5
+#: forum/skins/zapprotect/templates/node/accept_button.html:5
+#, python-format
+msgid "%(who)s has selected this answer as the correct answer"
+msgstr "%(who)s избра този отговор за верен"
+
+#: forum/skins/default/templates/node/accept_button.html:5
+#: forum/skins/zapprotect/templates/node/accept_button.html:5
+msgid "mark this answer as the accepted answer"
+msgstr "отбележи този отговор като приет"
+
+#: forum/skins/default/templates/node/comments.html:13
+#: forum/skins/zapprotect/templates/node/comments.html:13
+msgid "I like this comment (click again to cancel)"
+msgstr "Аз харесвам този коментар"
+
+#: forum/skins/default/templates/node/comments.html:17
+#: forum/skins/zapprotect/templates/node/comments.html:17
+#, fuzzy
+msgid "Edit comment"
+msgstr "Редактирай"
+
+#: forum/skins/default/templates/node/comments.html:21
+#: forum/skins/zapprotect/templates/node/comments.html:21
+#, fuzzy
+msgid "Delete comment"
+msgstr "Изтрий"
+
+#: forum/skins/default/templates/node/comments.html:34
+#: forum/skins/zapprotect/templates/node/comments.html:34
+#, python-format
+msgid "showing %(showing)s of %(total)s"
+msgstr "показани %(showing)s от %(total)s"
+
+#: forum/skins/default/templates/node/comments.html:36
+#: forum/skins/zapprotect/templates/node/comments.html:36
+msgid "show all"
+msgstr "покажи всички"
+
+#: forum/skins/default/templates/node/comments.html:39
+#: forum/skins/zapprotect/templates/node/comments.html:39
+#, fuzzy
+msgid "add new comment"
+msgstr "добави коментар"
+
+#: forum/skins/default/templates/node/comments.html:50
+#: forum/skins/zapprotect/templates/node/comments.html:50
+msgid "characters needed"
+msgstr "необходими символи"
+
+#: forum/skins/default/templates/node/comments.html:51
+#: forum/skins/zapprotect/templates/node/comments.html:51
+msgid "characters left"
+msgstr "оставащи символи"
+
+#: forum/skins/default/templates/node/comments.html:53
+#: forum/skins/zapprotect/templates/node/comments.html:53
+#, fuzzy
+msgid " comment"
+msgstr " коментар"
+
+#: forum/skins/default/templates/node/comments.html:54
+#: forum/skins/zapprotect/templates/node/comments.html:54
+#, fuzzy
+msgid " cancel"
+msgstr "Откажи"
+
+#: forum/skins/default/templates/node/comments.html:66
+#: forum/skins/zapprotect/templates/node/comments.html:66
+#, fuzzy
+msgid "just now"
+msgstr "Logout Now"
+
+#: forum/skins/default/templates/node/convert_to_comment.html:4
+#: forum/skins/zapprotect/templates/node/convert_to_comment.html:4
+#, fuzzy
+msgid "Place the comment under:"
+msgstr "Постави коментара под:"
+
+#: forum/skins/default/templates/node/favorite_mark.html:3
+#: forum/skins/zapprotect/templates/node/favorite_mark.html:3
+msgid "mark/unmark this question as favorite (click again to cancel)"
+msgstr "отбележи въпроса като любим"
+
+#: forum/skins/default/templates/node/post_controls.html:14
+#: forum/skins/zapprotect/templates/node/post_controls.html:14
+#, fuzzy
+msgid "more"
+msgstr "повече"
+
+#: forum/skins/default/templates/node/report.html:3
+#: forum/skins/zapprotect/templates/node/report.html:3
+msgid ""
+"Please select a reason bellow or use the text box to input your own reason."
+msgstr "Изберете някоя от посочените причини или използвайте поле."
+
+#: forum/skins/default/templates/node/vote_buttons.html:3
+#: forum/skins/zapprotect/templates/node/vote_buttons.html:3
+msgid "I like this post (click again to cancel)"
+msgstr "Аз харесвам тази публикация"
+
+#: forum/skins/default/templates/node/vote_buttons.html:7
+#: forum/skins/zapprotect/templates/node/vote_buttons.html:7
+msgid "current number of votes"
+msgstr "количество гласове"
+
+#: forum/skins/default/templates/node/vote_buttons.html:10
+#: forum/skins/zapprotect/templates/node/vote_buttons.html:10
+msgid "I dont like this post (click again to cancel)"
+msgstr "Аз не харесвам тази публикация"
+
+#: forum/skins/default/templates/node/wiki_symbol.html:5
+#: forum/skins/zapprotect/templates/node/wiki_symbol.html:5
+#, python-format
+msgid "This %(post_type)s is marked \"community wiki\"."
+msgstr "Този %(post_type)s е маркиран като \"уики общност\""
+
+#: forum/skins/default/templates/node/wiki_symbol.html:7
+#: forum/skins/zapprotect/templates/node/wiki_symbol.html:7
+#, python-format
+msgid "Feel free to <a href=\"%(edit_url)s\">edit it</a>."
+msgstr "Чуствайте се свободни да <a href=\"%(edit_url)s\">редактирате</a>"
+
+#: forum/skins/default/templates/notifications/answeraccepted.html:15
+#: forum/skins/zapprotect/templates/notifications/answeraccepted.html:15
+#, fuzzy, python-format
+msgid "%(prefix)s An answer to: %(question_title)s has been accepted"
+msgstr "Отговора на въпроса '%(question_title)s' беше приет"
+
+#: forum/skins/default/templates/notifications/answeraccepted.html:19
+#: forum/skins/zapprotect/templates/notifications/answeraccepted.html:19
+#, python-format
+msgid ""
+"\n"
+"            %(accepted_by_link)s has just accepted %(answer_author_link)s's "
+"answer on his question\n"
+"            %(question_link)s.\n"
+"            "
+msgstr ""
+"\n"
+"            %(accepted_by_link)s току що прие %(answer_author_link)s's "
+"отговор на неговия въпрос\n"
+"            %(question_link)s.\n"
+"            "
+
+#: forum/skins/default/templates/notifications/answeraccepted.html:27
+#: forum/skins/zapprotect/templates/notifications/answeraccepted.html:27
+#, python-format
+msgid ""
+"\n"
+"%(accepted_by)s has just accepted %(answer_author)s's answer on his "
+"question\n"
+"\"%(question_title)s\".\n"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/base.html:21
+#: forum/skins/default/templates/notifications/base_text.html:4
+#: forum/skins/zapprotect/templates/notifications/base.html:21
+#: forum/skins/zapprotect/templates/notifications/base_text.html:4
+msgid "Hello"
+msgstr "Здравейте"
+
+#: forum/skins/default/templates/notifications/base.html:24
+#: forum/skins/default/templates/notifications/base_text.html:9
+#: forum/skins/zapprotect/templates/notifications/base.html:24
+#: forum/skins/zapprotect/templates/notifications/base_text.html:9
+msgid "Thanks"
+msgstr "Поздрави"
+
+#: forum/skins/default/templates/notifications/base.html:26
+#: forum/skins/zapprotect/templates/notifications/base.html:26
+msgid "P.S. You can always fine-tune which notifications you receive"
+msgstr "P.S. Винаги можете да изберете кои известия да получавате"
+
+#: forum/skins/default/templates/notifications/base_text.html:13
+#: forum/skins/zapprotect/templates/notifications/base_text.html:13
+msgid "P.S. You can always fine-tune which notifications you receive here:"
+msgstr "P.S. Винаги можете да изберете кои известия да получавате тук:"
+
+#: forum/skins/default/templates/notifications/digest.html:14
+#: forum/skins/zapprotect/templates/notifications/digest.html:14
+#, fuzzy, python-format
+msgid "%(prefix)s Daily digest"
+msgstr "%(prefix)s Дневен бюлетин"
+
+#: forum/skins/default/templates/notifications/digest.html:18
+#: forum/skins/zapprotect/templates/notifications/digest.html:18
+#, fuzzy, python-format
+msgid ""
+"\n"
+"            This is a brief of what's going on the %(app_name)s community "
+"since our last update.\n"
+"            "
+msgstr ""
+"\n"
+"(един коментар)"
+
+#: forum/skins/default/templates/notifications/digest.html:26
+#: forum/skins/zapprotect/templates/notifications/digest.html:26
+#, fuzzy, python-format
+msgid ""
+"\n"
+"            There are %(new_member_count)s new members in the community. %"
+"(new_member_links)s were the most active so far.\n"
+"        "
+msgstr ""
+"Има %(new_member_count)s нови потребители в общността. %(new_member_links)s "
+"са били най-активни до сега.\n"
+
+#: forum/skins/default/templates/notifications/digest.html:30
+#: forum/skins/zapprotect/templates/notifications/digest.html:30
+#, fuzzy, python-format
+msgid ""
+"\n"
+"            %(new_member_links)s have joined the %(app_name)s community.\n"
+"        "
+msgstr ""
+"\n"
+"<div class=\"questions-count\">%(q_num)s</div><p>тагнати въпроса</p><p><span "
+"class=\"tag\">%(tagname)s</span></p>"
+
+#: forum/skins/default/templates/notifications/digest.html:46
+#: forum/skins/zapprotect/templates/notifications/digest.html:46
+#, fuzzy, python-format
+msgid ""
+"\n"
+"            %(new_question_count)s %(new_questions_link)s were posted since "
+"our last update.\n"
+"            "
+msgstr ""
+"\n"
+"(един коментар)"
+
+#: forum/skins/default/templates/notifications/digest.html:53
+#: forum/skins/zapprotect/templates/notifications/digest.html:53
+#, fuzzy
+msgid "We think you might like the following questions:"
+msgstr "Това може да е станало поради следните причини:"
+
+#: forum/skins/default/templates/notifications/digest.html:66
+#: forum/skins/zapprotect/templates/notifications/digest.html:66
+msgid ""
+"These new questions didn't get many attention from the community, but we "
+"think you may be able to help:"
+msgstr ""
+"Тези въпроси не са предизвикали много внимание в общността, но ние смятаме, "
+"че Вие бихте могли да помогнете:"
+
+#: forum/skins/default/templates/notifications/digest.html:78
+#: forum/skins/zapprotect/templates/notifications/digest.html:78
+#, python-format
+msgid ""
+"Meanwhile, some of your %(subscriptions_link)s have new updates since you "
+"last visited them:"
+msgstr ""
+"Междувременно, някои от Вашите %(subscriptions_link)s абонаменти имат "
+"обновявания след като последно сте ги прегледали:"
+
+#: forum/skins/default/templates/notifications/feedback.html:12
+#: forum/skins/zapprotect/templates/notifications/feedback.html:12
+#, fuzzy, python-format
+msgid "%(prefix)s Feedback message from %(app_name)s"
+msgstr "%(prefix)s съобщение за Обратна Връзка от %(app_name)s"
+
+#: forum/skins/default/templates/notifications/feedback.html:16
+#: forum/skins/default/templates/notifications/feedback.html:29
+#: forum/skins/zapprotect/templates/notifications/feedback.html:16
+#: forum/skins/zapprotect/templates/notifications/feedback.html:29
+msgid "Sender"
+msgstr "Изпратил"
+
+#: forum/skins/default/templates/notifications/feedback.html:16
+#: forum/skins/default/templates/notifications/feedback.html:29
+#: forum/skins/zapprotect/templates/notifications/feedback.html:16
+#: forum/skins/zapprotect/templates/notifications/feedback.html:29
+msgid "anonymous"
+msgstr "анонимен"
+
+#: forum/skins/default/templates/notifications/feedback.html:17
+#: forum/skins/default/templates/notifications/feedback.html:30
+#: forum/skins/default/templates/users/info.html:80
+#: forum/skins/zapprotect/templates/notifications/feedback.html:17
+#: forum/skins/zapprotect/templates/notifications/feedback.html:30
+#: forum/skins/zapprotect/templates/users/info.html:80
+msgid "email"
+msgstr "имейл"
+
+#: forum/skins/default/templates/notifications/feedback.html:23
+#: forum/skins/default/templates/notifications/feedback.html:33
+#: forum/skins/zapprotect/templates/notifications/feedback.html:23
+#: forum/skins/zapprotect/templates/notifications/feedback.html:33
+msgid "Message body:"
+msgstr "Съдържание:"
+
+#: forum/skins/default/templates/notifications/newanswer.html:16
+#: forum/skins/zapprotect/templates/notifications/newanswer.html:16
+#, fuzzy, python-format
+msgid "%(prefix)s New answer to: %(question_title)s"
+msgstr "%(prefix)s Нов отговор до: %(question_title)s"
+
+#: forum/skins/default/templates/notifications/newanswer.html:20
+#: forum/skins/zapprotect/templates/notifications/newanswer.html:20
+#, fuzzy, python-format
+msgid ""
+"\n"
+"            %(author_link)s has just posted a new answer on %(app_name)s to "
+"the question\n"
+"            %(question_link)s:\n"
+"            "
+msgstr ""
+"\n"
+"            %(author_link)s току що публикува нов отговор в %(app_name)s на "
+"въпроса \n"
+"            %(question_link)s:\n"
+"            "
+
+#: forum/skins/default/templates/notifications/newanswer.html:30
+#: forum/skins/default/templates/notifications/newanswer.html:40
+#: forum/skins/default/templates/notifications/newcomment.html:32
+#: forum/skins/default/templates/notifications/newcomment.html:43
+#: forum/skins/default/templates/notifications/newquestion.html:33
+#: forum/skins/default/templates/notifications/newquestion.html:43
+#: forum/skins/zapprotect/templates/notifications/newanswer.html:30
+#: forum/skins/zapprotect/templates/notifications/newanswer.html:40
+#: forum/skins/zapprotect/templates/notifications/newcomment.html:32
+#: forum/skins/zapprotect/templates/notifications/newcomment.html:43
+#: forum/skins/zapprotect/templates/notifications/newquestion.html:33
+#: forum/skins/zapprotect/templates/notifications/newquestion.html:43
+msgid "Don't forget to come over and cast your vote."
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newanswer.html:34
+#: forum/skins/zapprotect/templates/notifications/newanswer.html:34
+#, python-format
+msgid ""
+"\n"
+"%(answer_author)s has just posted a new answer on %(safe_app_name)s to the "
+"question\n"
+"\"%(question_title)s\":\n"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newcomment.html:17
+#: forum/skins/zapprotect/templates/notifications/newcomment.html:17
+#, fuzzy, python-format
+msgid "%(prefix)s New comment on: %(question_title)s"
+msgstr "Нов коментар на %(question_title)s"
+
+#: forum/skins/default/templates/notifications/newcomment.html:21
+#: forum/skins/zapprotect/templates/notifications/newcomment.html:21
+#, fuzzy, python-format
+msgid "%(author_link)s has just posted a comment on "
+msgstr ""
+"\n"
+"<div class=\"questions-count\">%(q_num)s</div><p>question tagged</p><p><span "
+"class=\"tag\">%(tagname)s</span></p>"
+
+#: forum/skins/default/templates/notifications/newcomment.html:23
+#: forum/skins/zapprotect/templates/notifications/newcomment.html:23
+#, python-format
+msgid "the answer posted by %(post_author)s to "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newcomment.html:25
+#: forum/skins/zapprotect/templates/notifications/newcomment.html:25
+#, fuzzy, python-format
+msgid "the question %(question_link)s"
+msgstr "Нов коментар на %(question_title)s"
+
+#: forum/skins/default/templates/notifications/newcomment.html:36
+#: forum/skins/zapprotect/templates/notifications/newcomment.html:36
+#, fuzzy, python-format
+msgid "%(comment_author)s has just posted a comment on "
+msgstr ""
+"\n"
+"<div class=\"questions-count\">%(q_num)s</div><p>question tagged</p><p><span "
+"class=\"tag\">%(tagname)s</span></p>"
+
+#: forum/skins/default/templates/notifications/newcomment.html:38
+#: forum/skins/zapprotect/templates/notifications/newcomment.html:38
+#, python-format
+msgid "the answer posted by %(safe_post_author)s to "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newcomment.html:40
+#: forum/skins/zapprotect/templates/notifications/newcomment.html:40
+#, fuzzy, python-format
+msgid "the question \"%(question_title)s\""
+msgstr "Нов коментар на %(question_title)s"
+
+#: forum/skins/default/templates/notifications/newmember.html:15
+#: forum/skins/zapprotect/templates/notifications/newmember.html:15
+#, fuzzy, python-format
+msgid "%(prefix)s %(safe_newmember_name)s is a new member on %(safe_app_name)s"
+msgstr "%(username)s е нов потребител на %(app_name)s"
+
+#: forum/skins/default/templates/notifications/newmember.html:19
+#: forum/skins/zapprotect/templates/notifications/newmember.html:19
+#, python-format
+msgid ""
+"\n"
+"            %(newmember_link)s has just joined %(app_name)s.\n"
+"            View <a style=\"%(a_style)s\" href=\"%(app_url)s%(newmember_url)s"
+"\">%(newmember_name)s's profile</a>.\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newmember.html:27
+#: forum/skins/zapprotect/templates/notifications/newmember.html:27
+#, python-format
+msgid ""
+"\n"
+"%(safe_newmember_name)s has just joined %(safe_app_name)s. You can visit %"
+"(safe_newmember_name)s's profile using the following url:\n"
+"%(app_url)s%(newmember_url)s\n"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newquestion.html:18
+#: forum/skins/zapprotect/templates/notifications/newquestion.html:18
+#, fuzzy, python-format
+msgid "%(prefix)s New question: %(question_title)s on %(safe_app_name)s"
+msgstr "Нов въпрос на %(app_name)s"
+
+#: forum/skins/default/templates/notifications/newquestion.html:22
+#: forum/skins/zapprotect/templates/notifications/newquestion.html:22
+#, python-format
+msgid ""
+"\n"
+"            %(author_link)s has just posted a new question on %(app_name)s, "
+"entitled\n"
+"            %(question_link)s\n"
+"             and tagged \"<em>%(tag_links)s</em>\". Here's what it says:\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newquestion.html:37
+#: forum/skins/zapprotect/templates/notifications/newquestion.html:37
+#, python-format
+msgid ""
+"\n"
+"%(question_author)s has just posted a new question on %(safe_app_name)s, "
+"entitled\n"
+"\"%(question_title)s\" and tagged %(question_tags)s:\n"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/base.html:13
+#: forum/skins/default/templates/osqaadmin/djstyle_base.html:22
+#: forum/skins/zapprotect/templates/osqaadmin/base.html:13
+#: forum/skins/zapprotect/templates/osqaadmin/djstyle_base.html:22
+msgid "OSQA administration area"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/base.html:26
+#: forum/skins/zapprotect/templates/osqaadmin/base.html:26
+msgid "Switch to django style interface"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/base.html:27
+#: forum/skins/zapprotect/templates/osqaadmin/base.html:27
+msgid "Administration menu"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/createuser.html:7
+#: forum/skins/zapprotect/templates/osqaadmin/createuser.html:7
+#, fuzzy
+msgid "Create User"
+msgstr "Парола <i>(напишете отново)</i>"
+
+#: forum/skins/default/templates/osqaadmin/createuser.html:10
+#: forum/skins/zapprotect/templates/osqaadmin/createuser.html:10
+#, fuzzy
+msgid "Quick creation of a new user"
+msgstr "answer"
+
+#: forum/skins/default/templates/osqaadmin/createuser.html:17
+#: forum/skins/default/templates/osqaadmin/edit_page.html:25
+#: forum/skins/default/templates/osqaadmin/nodeman.html:397
+#: forum/skins/default/templates/osqaadmin/set.html:16
+#: forum/skins/default/templates/users/preferences.html:25
+#: forum/skins/zapprotect/templates/osqaadmin/createuser.html:17
+#: forum/skins/zapprotect/templates/osqaadmin/edit_page.html:25
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:397
+#: forum/skins/zapprotect/templates/osqaadmin/set.html:16
+#: forum/skins/zapprotect/templates/users/preferences.html:25
+#, fuzzy
+msgid "Save"
+msgstr "Запази промените"
+
+#: forum/skins/default/templates/osqaadmin/dashboard.html:7
+#: forum/skins/default/templates/osqaadmin/djstyle_base.html:42
+#: forum/skins/default/templates/osqaadmin/index.html:7
+#: forum/skins/default/templates/osqaadmin/statistics.html:25
+#: forum/skins/default/templates/osqaadmin/statistics.html:26
+#: forum/skins/zapprotect/templates/osqaadmin/dashboard.html:7
+#: forum/skins/zapprotect/templates/osqaadmin/djstyle_base.html:42
+#: forum/skins/zapprotect/templates/osqaadmin/index.html:7
+#: forum/skins/zapprotect/templates/osqaadmin/statistics.html:25
+#: forum/skins/zapprotect/templates/osqaadmin/statistics.html:26
+msgid "Dashboard"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/dashboard.html:10
+#: forum/skins/default/templates/osqaadmin/index.html:10
+#: forum/skins/zapprotect/templates/osqaadmin/dashboard.html:10
+#: forum/skins/zapprotect/templates/osqaadmin/index.html:10
+msgid "Welcome to the OSQA administration area."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/dashboard.html:16
+#: forum/skins/zapprotect/templates/osqaadmin/dashboard.html:16
+msgid "Quick statistics"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/dashboard.html:19
+#: forum/skins/default/templates/osqaadmin/dashboard.html:24
+#: forum/skins/default/templates/osqaadmin/index.html:21
+#: forum/skins/default/templates/osqaadmin/index.html:26
+#: forum/skins/zapprotect/templates/osqaadmin/dashboard.html:19
+#: forum/skins/zapprotect/templates/osqaadmin/dashboard.html:24
+#: forum/skins/zapprotect/templates/osqaadmin/index.html:21
+#: forum/skins/zapprotect/templates/osqaadmin/index.html:26
+msgid "in the last 24 hours"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/dashboard.html:29
+#: forum/skins/default/templates/osqaadmin/index.html:31
+#: forum/skins/zapprotect/templates/osqaadmin/dashboard.html:29
+#: forum/skins/zapprotect/templates/osqaadmin/index.html:31
+msgid "user"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/dashboard.html:29
+#: forum/skins/default/templates/osqaadmin/index.html:31
+#: forum/skins/zapprotect/templates/osqaadmin/dashboard.html:29
+#: forum/skins/zapprotect/templates/osqaadmin/index.html:31
+msgid "joined in the last 24 hours"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/dashboard.html:36
+#: forum/skins/default/templates/osqaadmin/index.html:37
+#: forum/skins/zapprotect/templates/osqaadmin/dashboard.html:36
+#: forum/skins/zapprotect/templates/osqaadmin/index.html:37
+msgid "Site status"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/dashboard.html:40
+#: forum/skins/default/templates/osqaadmin/index.html:42
+#: forum/skins/zapprotect/templates/osqaadmin/dashboard.html:40
+#: forum/skins/zapprotect/templates/osqaadmin/index.html:42
+msgid ""
+"Your site is running in bootstrap mode, click the button below to revert to "
+"defaults."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/dashboard.html:43
+#: forum/skins/default/templates/osqaadmin/index.html:45
+#: forum/skins/zapprotect/templates/osqaadmin/dashboard.html:43
+#: forum/skins/zapprotect/templates/osqaadmin/index.html:45
+msgid ""
+"Your site is running in standard mode, click the button below to run in "
+"bootstrap mode."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/dashboard.html:45
+#: forum/skins/default/templates/osqaadmin/index.html:47
+#: forum/skins/zapprotect/templates/osqaadmin/dashboard.html:45
+#: forum/skins/zapprotect/templates/osqaadmin/index.html:47
+msgid ""
+"Your site is running with some customized settings, click the buttons below "
+"to run with defaults or in bootstrap mode"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/dashboard.html:49
+#: forum/skins/default/templates/osqaadmin/index.html:51
+#: forum/skins/zapprotect/templates/osqaadmin/dashboard.html:49
+#: forum/skins/zapprotect/templates/osqaadmin/index.html:51
+msgid "Are you sure you want to revert to the defaults?"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/dashboard.html:49
+#: forum/skins/default/templates/osqaadmin/index.html:51
+#: forum/skins/zapprotect/templates/osqaadmin/dashboard.html:49
+#: forum/skins/zapprotect/templates/osqaadmin/index.html:51
+msgid "revert to defaults"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/dashboard.html:52
+#: forum/skins/default/templates/osqaadmin/index.html:54
+#: forum/skins/zapprotect/templates/osqaadmin/dashboard.html:52
+#: forum/skins/zapprotect/templates/osqaadmin/index.html:54
+msgid "Are you sure you want to run bootstrap mode?"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/dashboard.html:52
+#: forum/skins/default/templates/osqaadmin/index.html:54
+#: forum/skins/zapprotect/templates/osqaadmin/dashboard.html:52
+#: forum/skins/zapprotect/templates/osqaadmin/index.html:54
+msgid "go bootstrap"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/dashboard.html:66
+#: forum/skins/default/templates/osqaadmin/index.html:71
+#: forum/skins/zapprotect/templates/osqaadmin/dashboard.html:66
+#: forum/skins/zapprotect/templates/osqaadmin/index.html:71
+msgid "Recent activity"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/djstyle_base.html:29
+#: forum/skins/zapprotect/templates/osqaadmin/djstyle_base.html:29
+#, fuzzy
+msgid "Administration Area"
+msgstr "администрация"
+
+#: forum/skins/default/templates/osqaadmin/djstyle_base.html:33
+#: forum/skins/zapprotect/templates/osqaadmin/djstyle_base.html:33
+#, fuzzy
+msgid "Welcome,"
+msgstr "Добре дошли в Zapprotect Q&amp;A"
+
+#: forum/skins/default/templates/osqaadmin/djstyle_base.html:35
+#: forum/skins/zapprotect/templates/osqaadmin/djstyle_base.html:35
+msgid "To standard interface"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/djstyle_base.html:36
+#: forum/skins/zapprotect/templates/osqaadmin/djstyle_base.html:36
+#, fuzzy
+msgid "Back to home page"
+msgstr "обратно на началната страница"
+
+#: forum/skins/default/templates/osqaadmin/djstyle_base.html:37
+#: forum/skins/zapprotect/templates/osqaadmin/djstyle_base.html:37
+#, fuzzy
+msgid "Log out"
+msgstr "Изход"
+
+#: forum/skins/default/templates/osqaadmin/djstyle_base.html:41
+#: forum/skins/zapprotect/templates/osqaadmin/djstyle_base.html:41
+#: rosetta/templates/rosetta/languages.html:6
+#: rosetta/templates/rosetta/pofile.html:18
+msgid "Home"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/djstyle_base.html:59
+#: forum/skins/zapprotect/templates/osqaadmin/djstyle_base.html:59
+msgid "Unpublished changes"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/djstyle_base.html:62
+#: forum/skins/zapprotect/templates/osqaadmin/djstyle_base.html:62
+msgid "Items marked with this icon have unpublished changes."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/djstyle_base.html:78
+#: forum/skins/zapprotect/templates/osqaadmin/djstyle_base.html:78
+msgid "Workflow settings"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/djstyle_base.html:88
+#: forum/skins/zapprotect/templates/osqaadmin/djstyle_base.html:88
+msgid "Forum settings"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/djstyle_base.html:96
+#: forum/skins/zapprotect/templates/osqaadmin/djstyle_base.html:96
+#, fuzzy
+msgid "Static content"
+msgstr "съдържание"
+
+#: forum/skins/default/templates/osqaadmin/djstyle_base.html:98
+#: forum/skins/zapprotect/templates/osqaadmin/djstyle_base.html:98
+#, fuzzy
+msgid "Custom Pages"
+msgstr "Тагове"
+
+#: forum/skins/default/templates/osqaadmin/djstyle_base.html:104
+#: forum/skins/default/templates/osqaadmin/djstyle_base.html:108
+#: forum/skins/default/templates/osqaadmin/djstyle_base.html:112
+#: forum/skins/default/templates/osqaadmin/djstyle_base.html:122
+#: forum/skins/zapprotect/templates/osqaadmin/djstyle_base.html:104
+#: forum/skins/zapprotect/templates/osqaadmin/djstyle_base.html:108
+#: forum/skins/zapprotect/templates/osqaadmin/djstyle_base.html:112
+#: forum/skins/zapprotect/templates/osqaadmin/djstyle_base.html:122
+msgid "Unsaved changes"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/djstyle_base.html:117
+#: forum/skins/zapprotect/templates/osqaadmin/djstyle_base.html:117
+#, fuzzy
+msgid "Other settings"
+msgstr "Опции за оторизиране"
+
+#: forum/skins/default/templates/osqaadmin/djstyle_base.html:128
+#: forum/skins/zapprotect/templates/osqaadmin/djstyle_base.html:128
+msgid "Tools"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/djstyle_base.html:130
+#: forum/skins/default/templates/osqaadmin/maintenance.html:5
+#: forum/skins/default/templates/osqaadmin/maintenance.html:6
+#: forum/skins/zapprotect/templates/osqaadmin/djstyle_base.html:130
+#: forum/skins/zapprotect/templates/osqaadmin/maintenance.html:5
+#: forum/skins/zapprotect/templates/osqaadmin/maintenance.html:6
+msgid "Maintenance mode"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/djstyle_base.html:131
+#: forum/skins/default/templates/osqaadmin/flagged_posts.html:6
+#: forum/skins/default/templates/osqaadmin/flagged_posts.html:7
+#: forum/skins/default/templates/osqaadmin/flagged_posts.html:13
+#: forum/skins/zapprotect/templates/osqaadmin/djstyle_base.html:131
+#: forum/skins/zapprotect/templates/osqaadmin/flagged_posts.html:6
+#: forum/skins/zapprotect/templates/osqaadmin/flagged_posts.html:7
+#: forum/skins/zapprotect/templates/osqaadmin/flagged_posts.html:13
+msgid "Flagged Posts"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/edit_page.html:5
+#: forum/skins/default/templates/osqaadmin/edit_page.html:8
+#: forum/skins/zapprotect/templates/osqaadmin/edit_page.html:5
+#: forum/skins/zapprotect/templates/osqaadmin/edit_page.html:8
+#, fuzzy
+msgid "Editing page"
+msgstr "Редактирай отговора"
+
+#: forum/skins/default/templates/osqaadmin/edit_page.html:7
+#: forum/skins/zapprotect/templates/osqaadmin/edit_page.html:7
+msgid "Static Pages"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/edit_page.html:8
+#: forum/skins/zapprotect/templates/osqaadmin/edit_page.html:8
+#, fuzzy
+msgid "Creating page"
+msgstr "текуща страница"
+
+#: forum/skins/default/templates/osqaadmin/edit_page.html:11
+#: forum/skins/default/templates/osqaadmin/static_pages.html:12
+#: forum/skins/zapprotect/templates/osqaadmin/edit_page.html:11
+#: forum/skins/zapprotect/templates/osqaadmin/static_pages.html:12
+#, fuzzy
+msgid "New page"
+msgstr "следваща страница"
+
+#: forum/skins/default/templates/osqaadmin/edit_page.html:12
+#: forum/skins/zapprotect/templates/osqaadmin/edit_page.html:12
+msgid "Published"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/edit_page.html:12
+#: forum/skins/zapprotect/templates/osqaadmin/edit_page.html:12
+msgid "Unpublished"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/edit_page.html:23
+#: forum/skins/default/templates/osqaadmin/static_pages.html:21
+#: forum/skins/zapprotect/templates/osqaadmin/edit_page.html:23
+#: forum/skins/zapprotect/templates/osqaadmin/static_pages.html:21
+#, fuzzy
+msgid "Edit"
+msgstr "редактирай"
+
+#: forum/skins/default/templates/osqaadmin/edit_page.html:28
+#: forum/skins/zapprotect/templates/osqaadmin/edit_page.html:28
+msgid "Unpublish"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/edit_page.html:30
+#: forum/skins/zapprotect/templates/osqaadmin/edit_page.html:30
+msgid "Publish"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/flagged_posts.html:8
+#: forum/skins/zapprotect/templates/osqaadmin/flagged_posts.html:8
+msgid "This are the posts that have been flagged by users."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:17
+#: forum/skins/zapprotect/templates/osqaadmin/index.html:17
+msgid "Site statistics"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:65
+#: forum/skins/zapprotect/templates/osqaadmin/index.html:65
+msgid "Recalculate scores and reputation"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:66
+#: forum/skins/zapprotect/templates/osqaadmin/index.html:66
+msgid "This is a heavy operation, are you sure?"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:66
+#: forum/skins/zapprotect/templates/osqaadmin/index.html:66
+msgid "Recalculate"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/maintenance.html:7
+#: forum/skins/zapprotect/templates/osqaadmin/maintenance.html:7
+msgid ""
+"Maintainance mode allows you to close your site for maintainance, allowing "
+"only a predetermined set of ip addresses to access it normally."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/maintenance.html:12
+#: forum/skins/zapprotect/templates/osqaadmin/maintenance.html:12
+msgid "Your site is currently running on maintenance mode."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/maintenance.html:13
+#: forum/skins/zapprotect/templates/osqaadmin/maintenance.html:13
+msgid "You can adjust the settings bellow"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/maintenance.html:19
+#: forum/skins/zapprotect/templates/osqaadmin/maintenance.html:19
+#, fuzzy
+msgid "Adjust settings"
+msgstr ""
+"<span class='big strong'>Adjust frequency of email updates.</span> Receive "
+"updates on interesting questions by email, <strong><br/>help the community</"
+"strong> by answering questions of your colleagues. If you do not wish to "
+"receive emails - select 'no email' on all items below.<br/>Updates are only "
+"sent when there is any new activity on selected items."
+
+#: forum/skins/default/templates/osqaadmin/maintenance.html:20
+#: forum/skins/zapprotect/templates/osqaadmin/maintenance.html:20
+#, fuzzy
+msgid "Open site"
+msgstr "Уеб сайт"
+
+#: forum/skins/default/templates/osqaadmin/maintenance.html:22
+#: forum/skins/zapprotect/templates/osqaadmin/maintenance.html:22
+msgid "Close for maintenance"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/moderation.html:5
+#: forum/skins/default/templates/osqaadmin/moderation.html:6
+#: forum/skins/zapprotect/templates/osqaadmin/moderation.html:5
+#: forum/skins/zapprotect/templates/osqaadmin/moderation.html:6
+#, fuzzy
+msgid "Moderation"
+msgstr "Местоположение"
+
+#: forum/skins/default/templates/osqaadmin/moderation.html:7
+#: forum/skins/zapprotect/templates/osqaadmin/moderation.html:7
+msgid ""
+"These tools allow you to search for undesired behaviours and cheating "
+"patterns."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/moderation.html:13
+#: forum/skins/zapprotect/templates/osqaadmin/moderation.html:13
+msgid "Verify:"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/moderation.html:16
+#: forum/skins/zapprotect/templates/osqaadmin/moderation.html:16
+msgid "highest ranking users"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/moderation.html:17
+#: forum/skins/zapprotect/templates/osqaadmin/moderation.html:17
+#, fuzzy
+msgid "newer users"
+msgstr "най-новите"
+
+#: forum/skins/default/templates/osqaadmin/moderation.html:18
+#: forum/skins/zapprotect/templates/osqaadmin/moderation.html:18
+#, fuzzy
+msgid "older users"
+msgstr "най-старите"
+
+#: forum/skins/default/templates/osqaadmin/moderation.html:19
+#: forum/skins/zapprotect/templates/osqaadmin/moderation.html:19
+msgid "users with these ids"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/moderation.html:23
+#: forum/skins/zapprotect/templates/osqaadmin/moderation.html:23
+msgid "(Comma separated list of user ids)"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/moderation.html:25
+#: forum/skins/default/templates/osqaadmin/nodeman.html:419
+#: forum/skins/zapprotect/templates/osqaadmin/moderation.html:25
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:419
+#: rosetta/templates/rosetta/pofile.html:44
+msgid "Go"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/moderation.html:50
+#: forum/skins/zapprotect/templates/osqaadmin/moderation.html:50
+msgid "Possible cheaters"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/moderation.html:56
+#: forum/skins/default/templates/osqaadmin/moderation.html:69
+#: forum/skins/zapprotect/templates/osqaadmin/moderation.html:56
+#: forum/skins/zapprotect/templates/osqaadmin/moderation.html:69
+#, fuzzy
+msgid "Email"
+msgstr ""
+"<strong>Your Email</strong> (<i>must be valid, never shown to others</i>)"
+
+#: forum/skins/default/templates/osqaadmin/moderation.html:58
+#: forum/skins/default/templates/osqaadmin/moderation.html:82
+#: forum/skins/zapprotect/templates/osqaadmin/moderation.html:58
+#: forum/skins/zapprotect/templates/osqaadmin/moderation.html:82
+#, fuzzy
+msgid "Validated"
+msgstr "обновено"
+
+#: forum/skins/default/templates/osqaadmin/moderation.html:60
+#: forum/skins/default/templates/osqaadmin/moderation.html:84
+#: forum/skins/zapprotect/templates/osqaadmin/moderation.html:60
+#: forum/skins/zapprotect/templates/osqaadmin/moderation.html:84
+msgid "Not validated"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/moderation.html:63
+#: forum/skins/zapprotect/templates/osqaadmin/moderation.html:63
+#, fuzzy
+msgid "Reputation:"
+msgstr "karma"
+
+#: forum/skins/default/templates/osqaadmin/moderation.html:70
+#: forum/skins/zapprotect/templates/osqaadmin/moderation.html:70
+#, fuzzy
+msgid "Reputation"
+msgstr "karma"
+
+#: forum/skins/default/templates/osqaadmin/moderation.html:71
+#: forum/skins/zapprotect/templates/osqaadmin/moderation.html:71
+msgid "Affecting actions"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/moderation.html:72
+#: forum/skins/zapprotect/templates/osqaadmin/moderation.html:72
+msgid "Cross ips"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/moderation.html:73
+#: forum/skins/zapprotect/templates/osqaadmin/moderation.html:73
+#, fuzzy
+msgid "Cheating score"
+msgstr "Смяна на паролата"
+
+#: forum/skins/default/templates/osqaadmin/moderation.html:76
+#: forum/skins/zapprotect/templates/osqaadmin/moderation.html:76
+#, fuzzy
+msgid "Possible fake accounts"
+msgstr "Изтрий профила"
+
+#: forum/skins/default/templates/osqaadmin/moderation.html:89
+#: forum/skins/default/templates/osqaadmin/moderation.html:90
+#: forum/skins/zapprotect/templates/osqaadmin/moderation.html:89
+#: forum/skins/zapprotect/templates/osqaadmin/moderation.html:90
+#, fuzzy
+msgid "out of"
+msgstr "Излез сега"
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:73
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:73
+msgid "rep"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:102
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:102
+#, fuzzy
+msgid "uses"
+msgstr "потребители"
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:261
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:261
+#, fuzzy
+msgid "Node manager"
+msgstr "най-старите"
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:264
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:264
+msgid "Nodes bulk management"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:277
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:277
+msgid "reset text filter"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:289
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:289
+msgid "Body"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:294
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:294
+msgid "Title and Body"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:324
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:324
+#, fuzzy
+msgid "Filter"
+msgstr "сребро"
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:324
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:324
+msgid "Click to show/hide"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:326
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:326
+msgid "By type"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:329
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:329
+msgid "click to clear the type filter"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:329
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:329
+msgid "all"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:332
+#: forum/skins/default/templates/osqaadmin/nodeman.html:343
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:332
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:343
+msgid "click to remove from the filter"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:332
+#: forum/skins/default/templates/osqaadmin/nodeman.html:343
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:332
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:343
+msgid "click to add to the filter"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:337
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:337
+msgid "By state"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:340
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:340
+msgid "click to clear the state filter"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:340
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:340
+msgid "any"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:349
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:349
+msgid "Match any selected"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:350
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:350
+msgid "Match all selected"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:354
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:354
+msgid "By author(s)"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:356
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:356
+msgid "No users selected, use the box bellow to add users to the filter."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:366
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:366
+msgid "Click on the cross next to a user name to remove it from the filter."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:370
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:370
+#, fuzzy
+msgid "By tag(s)"
+msgstr "тагове"
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:372
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:372
+msgid "No tags selected, use the box bellow to add tags to the filter."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:382
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:382
+msgid "Click on the cross next to a tag name to remove it from the filter."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:386
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:386
+msgid "Pre defined"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:388
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:388
+msgid "There are no saved filters. Click bellow to add."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:396
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:396
+#, fuzzy
+msgid "Filter name..."
+msgstr "потребителско име"
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:397
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:397
+msgid "Click to save the current filter"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:400
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:400
+msgid "Show"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:403
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:403
+msgid "Refresh"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:410
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:410
+#, fuzzy
+msgid "Action"
+msgstr "Местоположение"
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:413
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:413
+#, fuzzy
+msgid "Mark deleted"
+msgstr "[изтрито]"
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:414
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:414
+#, fuzzy
+msgid "Undelete"
+msgstr "[изтрито]"
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:415
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:415
+#, fuzzy
+msgid "Delete completely"
+msgstr "post a comment"
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:416
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:416
+#, fuzzy
+msgid "Close (questions only)"
+msgstr "<strong>Newest</strong> questions are shown first."
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:419
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:419
+msgid "Run the selected action"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:442
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:442
+msgid "Type"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:443
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:443
+msgid "Summary"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:445
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:445
+#, fuzzy
+msgid "State"
+msgstr "заглавие"
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:447
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:447
+msgid "Author"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:450
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:450
+msgid "Added at"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:453
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:453
+msgid "Score"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:456
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:456
+msgid "Last activity by"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:459
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:459
+msgid "Last activity at"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:461
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:461
+#: forum_modules/exporter/exporter.py:326
+#: forum_modules/exporter/importer.py:357
+#, fuzzy
+msgid "Tags"
+msgstr "тагове"
+
+#: forum/skins/default/templates/osqaadmin/nodeman.html:490
+#: forum/skins/zapprotect/templates/osqaadmin/nodeman.html:490
+msgid "by"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/set.html:18
+#: forum/skins/zapprotect/templates/osqaadmin/set.html:18
+#, fuzzy
+msgid "Preview"
+msgstr "преглеждания"
+
+#: forum/skins/default/templates/osqaadmin/set.html:20
+#: forum/skins/zapprotect/templates/osqaadmin/set.html:20
+msgid "Reset Changes"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/static_pages.html:5
+#: forum/skins/default/templates/osqaadmin/static_pages.html:6
+#: forum/skins/zapprotect/templates/osqaadmin/static_pages.html:5
+#: forum/skins/zapprotect/templates/osqaadmin/static_pages.html:6
+msgid "Static pages"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/static_pages.html:7
+#: forum/skins/zapprotect/templates/osqaadmin/static_pages.html:7
+msgid "Allows you to create a set of static pages"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/static_pages.html:10
+#: forum/skins/zapprotect/templates/osqaadmin/static_pages.html:10
+msgid "Select page to edit"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/static_pages.html:16
+#: forum/skins/zapprotect/templates/osqaadmin/static_pages.html:16
+#, fuzzy
+msgid "Pages"
+msgstr "Точки"
+
+#: forum/skins/default/templates/osqaadmin/statistics.html:27
+#: forum/skins/zapprotect/templates/osqaadmin/statistics.html:27
+msgid ""
+"Some simple graphics to help you get a notion of whats going on in your site."
+msgstr ""
+
+#: forum/skins/default/templates/paginator/sort_tabs.html:9
+#: forum/skins/zapprotect/templates/paginator/sort_tabs.html:9
+msgid "Check to make the sort order sticky"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/item.html:11
+#: forum/skins/zapprotect/templates/question_list/item.html:11
+#: forum/views/commands.py:66 forum/views/commands.py:69
+#: forum/views/commands.py:112
+msgid "vote"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/item.html:13
+#: forum/skins/zapprotect/templates/question_list/item.html:13
+msgid "this question has an accepted answer"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/item.html:19
+#: forum/skins/zapprotect/templates/question_list/item.html:19
+#, fuzzy
+msgid "view"
+msgstr "преглеждания"
+
+#: forum/skins/default/templates/question_list/related_tags.html:6
+#: forum/skins/zapprotect/templates/question_list/related_tags.html:6
+msgid "Related tags"
+msgstr "Tags"
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:4
+#: forum/skins/zapprotect/templates/question_list/sort_tabs.html:4
+msgid "most recently updated questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:4
+#: forum/skins/zapprotect/templates/question_list/sort_tabs.html:4
+#: forum/views/readers.py:44
+msgid "active"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:5
+#: forum/skins/zapprotect/templates/question_list/sort_tabs.html:5
+msgid "most recently asked questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:5
+#: forum/skins/zapprotect/templates/question_list/sort_tabs.html:5
+#: forum/views/readers.py:45 forum/views/readers.py:61
+#: forum/views/readers.py:263 forum/views/users.py:40 forum/views/users.py:53
+msgid "newest"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:6
+#: forum/skins/zapprotect/templates/question_list/sort_tabs.html:6
+msgid "hottest questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:6
+#: forum/skins/zapprotect/templates/question_list/sort_tabs.html:6
+#: forum/views/readers.py:46
+msgid "hottest"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:7
+#: forum/skins/zapprotect/templates/question_list/sort_tabs.html:7
+msgid "most voted questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:7
+#: forum/skins/zapprotect/templates/question_list/sort_tabs.html:7
+#: forum/views/readers.py:47
+msgid "most voted"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/subscription_item.html:4
+#: forum/skins/zapprotect/templates/question_list/subscription_item.html:4
+#, fuzzy
+msgid "Unsubscribe"
+msgstr "махни абонамента ми"
+
+#: forum/skins/default/templates/question_list/subscription_item.html:8
+#: forum/skins/zapprotect/templates/question_list/subscription_item.html:8
+msgid "Last checked"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:5
+#: forum/skins/zapprotect/templates/question_list/title.html:5
+msgid "Found by tags"
+msgstr "Tagged questions"
+
+#: forum/skins/default/templates/question_list/title.html:9
+#: forum/skins/zapprotect/templates/question_list/title.html:9
+msgid "Search results"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:11
+#: forum/skins/zapprotect/templates/question_list/title.html:11
+msgid "Found by title"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:15
+#: forum/skins/zapprotect/templates/question_list/title.html:15
+msgid "Unanswered questions"
+msgstr "Въпроси без отговор"
+
+#: forum/skins/default/templates/question_list/title.html:20
+#: forum/skins/zapprotect/templates/question_list/title.html:20
+#: forum/views/readers.py:141
+#, fuzzy
+msgid "All Questions"
+msgstr "Въпроси"
+
+#: forum/skins/default/templates/sidebar/markdown_help.html:3
+#: forum/skins/zapprotect/templates/sidebar/markdown_help.html:3
+#, fuzzy
+msgid "Markdown Basics"
+msgstr "Markdown съвети"
+
+#: forum/skins/default/templates/sidebar/markdown_help.html:6
+#: forum/skins/zapprotect/templates/sidebar/markdown_help.html:6
+msgid "*italic* or __italic__"
+msgstr "*италик* или __италик__"
+
+#: forum/skins/default/templates/sidebar/markdown_help.html:9
+#: forum/skins/zapprotect/templates/sidebar/markdown_help.html:9
+msgid "**bold** or __bold__"
+msgstr "**дебел** или __дебел__"
+
+#: forum/skins/default/templates/sidebar/markdown_help.html:12
+#: forum/skins/zapprotect/templates/sidebar/markdown_help.html:12
+msgid "link"
+msgstr "връзка"
+
+#: forum/skins/default/templates/sidebar/markdown_help.html:12
+#: forum/skins/default/templates/sidebar/markdown_help.html:17
+#: forum/skins/zapprotect/templates/sidebar/markdown_help.html:12
+#: forum/skins/zapprotect/templates/sidebar/markdown_help.html:17
+msgid "text"
+msgstr "текст"
+
+#: forum/skins/default/templates/sidebar/markdown_help.html:17
+#: forum/skins/zapprotect/templates/sidebar/markdown_help.html:17
+msgid "image"
+msgstr "снимка"
+
+#: forum/skins/default/templates/sidebar/markdown_help.html:21
+#: forum/skins/zapprotect/templates/sidebar/markdown_help.html:21
+msgid "numbered list:"
+msgstr "подреден лист:"
+
+#: forum/skins/default/templates/sidebar/markdown_help.html:26
+#: forum/skins/zapprotect/templates/sidebar/markdown_help.html:26
+msgid ""
+"to add a line break simply add two spaces to where you would like the new "
+"line to be."
+msgstr ""
+
+#: forum/skins/default/templates/sidebar/markdown_help.html:29
+#: forum/skins/zapprotect/templates/sidebar/markdown_help.html:29
+msgid "basic HTML tags are also supported"
+msgstr "основни HTML тагове също се поддържат"
+
+#: forum/skins/default/templates/sidebar/markdown_help.html:33
+#: forum/skins/zapprotect/templates/sidebar/markdown_help.html:33
+msgid "learn more about Markdown"
+msgstr "научете повече относно Markdown"
+
+#: forum/skins/default/templates/sidebar/recent_awards.html:4
+#: forum/skins/zapprotect/templates/sidebar/recent_awards.html:4
+msgid "Recent awards"
+msgstr "Последни точки"
+
+#: forum/skins/default/templates/sidebar/recent_awards.html:15
+#: forum/skins/zapprotect/templates/sidebar/recent_awards.html:15
+msgid "all awards"
+msgstr "всички точки"
+
+#: forum/skins/default/templates/sidebar/recent_tags.html:4
+#: forum/skins/zapprotect/templates/sidebar/recent_tags.html:4
+msgid "Recent tags"
+msgstr "Последни тагове"
+
+#: forum/skins/default/templates/sidebar/recent_tags.html:12
+#: forum/skins/zapprotect/templates/sidebar/recent_tags.html:12
+msgid "popular tags"
+msgstr "популярни тагове"
+
+#: forum/skins/default/templates/users/edit.html:6
+#: forum/skins/zapprotect/templates/users/edit.html:6
+msgid "Edit user profile"
+msgstr "Редактирай потребителския профил"
+
+#: forum/skins/default/templates/users/edit.html:45
+#: forum/skins/zapprotect/templates/users/edit.html:45
+msgid "image associated with your email address"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:45
+#: forum/skins/zapprotect/templates/users/edit.html:45
+#, fuzzy
+msgid "gravatar"
+msgstr "Какво е Gravatar?"
+
+#: forum/skins/default/templates/users/edit.html:50
+#: forum/skins/default/templates/users/info.html:39
+#: forum/skins/zapprotect/templates/users/edit.html:50
+#: forum/skins/zapprotect/templates/users/info.html:39
+msgid "Registered user"
+msgstr "Регистриран потребител"
+
+#: forum/skins/default/templates/users/edit.html:57
+#: forum/skins/zapprotect/templates/users/edit.html:57
+msgid "Screen Name"
+msgstr "Публично име"
+
+#: forum/skins/default/templates/users/edit.html:98
+#: forum/skins/default/templates/users/subscriptions_settings.html:119
+#: forum/skins/zapprotect/templates/users/edit.html:98
+#: forum/skins/zapprotect/templates/users/subscriptions_settings.html:119
+msgid "Update"
+msgstr "Обнови"
+
+#: forum/skins/default/templates/users/info.html:26
+#: forum/skins/default/templates/users/signature.html:8
+#: forum/skins/zapprotect/templates/users/info.html:26
+#: forum/skins/zapprotect/templates/users/signature.html:8
+#: forum/views/users.py:39
+msgid "reputation"
+msgstr "Карма"
+
+#: forum/skins/default/templates/users/info.html:28
+#: forum/skins/zapprotect/templates/users/info.html:28
+#, fuzzy
+msgid "Suspended"
+msgstr "Преостановено"
+
+#: forum/skins/default/templates/users/info.html:43
+#: forum/skins/zapprotect/templates/users/info.html:43
+msgid "real name"
+msgstr "Истинско име"
+
+#: forum/skins/default/templates/users/info.html:48
+#: forum/skins/zapprotect/templates/users/info.html:48
+msgid "member for"
+msgstr "member since"
+
+#: forum/skins/default/templates/users/info.html:53
+#: forum/skins/zapprotect/templates/users/info.html:53
+msgid "last seen"
+msgstr "последно видян"
+
+#: forum/skins/default/templates/users/info.html:59
+#: forum/skins/zapprotect/templates/users/info.html:59
+msgid "user's website"
+msgstr "потребителски сайт"
+
+#: forum/skins/default/templates/users/info.html:65
+#: forum/skins/zapprotect/templates/users/info.html:65
+msgid "location"
+msgstr "местоположение"
+
+#: forum/skins/default/templates/users/info.html:73
+#: forum/skins/zapprotect/templates/users/info.html:73
+msgid "age"
+msgstr "възраст"
+
+#: forum/skins/default/templates/users/info.html:74
+#: forum/skins/zapprotect/templates/users/info.html:74
+msgid "age unit"
+msgstr "years old"
+
+#: forum/skins/default/templates/users/info.html:84
+#: forum/skins/zapprotect/templates/users/info.html:84
+msgid "not validated"
+msgstr "не е проверено"
+
+#: forum/skins/default/templates/users/info.html:95
+#: forum/skins/zapprotect/templates/users/info.html:95
+msgid "todays unused votes"
+msgstr "неизползвани гласове днес"
+
+#: forum/skins/default/templates/users/info.html:96
+#: forum/skins/zapprotect/templates/users/info.html:96
+msgid "votes left"
+msgstr "останали гласове"
+
+#: forum/skins/default/templates/users/karma_bonus.html:5
+#: forum/skins/zapprotect/templates/users/karma_bonus.html:5
+msgid "Points"
+msgstr "Точки"
+
+#: forum/skins/default/templates/users/menu.html:4
+#: forum/skins/zapprotect/templates/users/menu.html:4
+#, fuzzy
+msgid "User tools"
+msgstr "Потребителски вход"
+
+#: forum/skins/default/templates/users/online_users.html:6
+#: forum/skins/default/templates/users/online_users.html:23
+#: forum/skins/zapprotect/templates/users/online_users.html:6
+#: forum/skins/zapprotect/templates/users/online_users.html:23
+#, fuzzy
+msgid "Users Online"
+msgstr "Потребителски вход"
+
+#: forum/skins/default/templates/users/online_users.html:29
+#: forum/skins/default/templates/users/users.html:29
+#: forum/skins/zapprotect/templates/users/online_users.html:29
+#: forum/skins/zapprotect/templates/users/users.html:29
+#, python-format
+msgid "users matching query %(suser)s:"
+msgstr ""
+
+#: forum/skins/default/templates/users/online_users.html:33
+#: forum/skins/default/templates/users/users.html:33
+#: forum/skins/zapprotect/templates/users/online_users.html:33
+#: forum/skins/zapprotect/templates/users/users.html:33
+msgid "Nothing found."
+msgstr ""
+
+#: forum/skins/default/templates/users/preferences.html:6
+#: forum/skins/zapprotect/templates/users/preferences.html:6
+msgid "Preferences"
+msgstr ""
+
+#: forum/skins/default/templates/users/preferences.html:10
+#: forum/skins/zapprotect/templates/users/preferences.html:10
+msgid "Here you can set some personal preferences."
+msgstr ""
+
+#: forum/skins/default/templates/users/preferences.html:16
+#: forum/skins/zapprotect/templates/users/preferences.html:16
+msgid "Navigation:"
+msgstr ""
+
+#: forum/skins/default/templates/users/preferences.html:21
+#: forum/skins/zapprotect/templates/users/preferences.html:21
+msgid "Allways remember the sort order I apply to the lists I view"
+msgstr ""
+
+#: forum/skins/default/templates/users/signature.html:11
+#: forum/skins/default/templates/users/signature.html:17
+#: forum/skins/default/templates/users/signature.html:23
+#: forum/skins/zapprotect/templates/users/signature.html:11
+#: forum/skins/zapprotect/templates/users/signature.html:17
+#: forum/skins/zapprotect/templates/users/signature.html:23
+#: forum/templatetags/extra_tags.py:76 forum/views/meta.py:81
+msgid "badges"
+msgstr "точки"
+
+#: forum/skins/default/templates/users/signature.html:31
+#: forum/skins/zapprotect/templates/users/signature.html:31
+#: forum/templatetags/extra_tags.py:49
+msgid "(suspended)"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:13
+#: forum/skins/zapprotect/templates/users/stats.html:13
+#, fuzzy, python-format
+msgid ""
+"\n"
+"                <span class=\"count\">%(counter)s</span> Question\n"
+"                "
+msgid_plural ""
+"\n"
+"                <span class=\"count\">%(counter)s</span> Questions\n"
+"                "
+msgstr[0] ""
+"\n"
+"<div class=\"questions-count\">%(q_num)s</div><p>question without an "
+"accepted answer</p>"
+msgstr[1] ""
+"\n"
+"<div class=\"questions-count\">%(q_num)s</div><p>questions without an "
+"accepted answer</p>"
+
+#: forum/skins/default/templates/users/stats.html:35
+#: forum/skins/zapprotect/templates/users/stats.html:35
+#, fuzzy, python-format
+msgid ""
+"\n"
+"                <span class=\"count\">%(counter)s</span> Answer\n"
+"                "
+msgid_plural ""
+"\n"
+"                <span class=\"count\">%(counter)s</span> Answers\n"
+"                "
+msgstr[0] ""
+"\n"
+"(one comment)"
+msgstr[1] ""
+"\n"
+"(one comment)"
+
+#: forum/skins/default/templates/users/stats.html:49
+#: forum/skins/zapprotect/templates/users/stats.html:49
+#, python-format
+msgid "the answer has been voted for %(vote_count)s times"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:49
+#: forum/skins/zapprotect/templates/users/stats.html:49
+msgid "this answer has been selected as correct"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:67
+#: forum/skins/zapprotect/templates/users/stats.html:67
+#, fuzzy, python-format
+msgid ""
+"\n"
+"                    <span class=\"count\">%(cnt)s</span> Vote\n"
+"                "
+msgid_plural ""
+"\n"
+"                    <span class=\"count\">%(cnt)s</span> Votes\n"
+"                "
+msgstr[0] ""
+"\n"
+"(one comment)"
+msgstr[1] ""
+"\n"
+"(one comment)"
+
+#: forum/skins/default/templates/users/stats.html:78
+#: forum/skins/zapprotect/templates/users/stats.html:78
+msgid "thumb up"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:79
+#: forum/skins/zapprotect/templates/users/stats.html:79
+msgid "user has voted up this many times"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:83
+#: forum/skins/zapprotect/templates/users/stats.html:83
+msgid "thumb down"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:84
+#: forum/skins/zapprotect/templates/users/stats.html:84
+msgid "user voted down this many times"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:93
+#: forum/skins/zapprotect/templates/users/stats.html:93
+#, fuzzy, python-format
+msgid ""
+"\n"
+"                    <span class=\"count\">%(counter)s</span> Tag\n"
+"                "
+msgid_plural ""
+"\n"
+"                    <span class=\"count\">%(counter)s</span> Tags\n"
+"                "
+msgstr[0] ""
+"\n"
+"(one comment)"
+msgstr[1] ""
+"\n"
+"(one comment)"
+
+#: forum/skins/default/templates/users/stats.html:106
+#: forum/skins/zapprotect/templates/users/stats.html:106
+#, python-format
+msgid ""
+"see other questions with %(view_user)s's contributions tagged '%(tag_name)s' "
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:121
+#: forum/skins/zapprotect/templates/users/stats.html:121
+#, python-format
+msgid ""
+"\n"
+"            <span class=\"count\">%(counter)s</span> Badge\n"
+"            "
+msgid_plural ""
+"\n"
+"            <span class=\"count\">%(counter)s</span> Badges\n"
+"            "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/subscriptions_management.html:6
+#: forum/skins/zapprotect/templates/users/subscriptions_management.html:6
+msgid "Manage your current subscriptions"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions_management.html:9
+#: forum/skins/zapprotect/templates/users/subscriptions_management.html:9
+msgid "don't show auto-subscribe"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions_management.html:11
+#: forum/skins/zapprotect/templates/users/subscriptions_management.html:11
+#, fuzzy
+msgid "show auto-subscribe"
+msgstr "махни абонамента ми"
+
+#: forum/skins/default/templates/users/subscriptions_settings.html:5
+#: forum/skins/zapprotect/templates/users/subscriptions_settings.html:5
+#, fuzzy
+msgid "Notifications and subscription settings"
+msgstr ""
+"<span class='big strong'>Adjust frequency of email updates.</span> Receive "
+"updates on interesting questions by email, <strong><br/>help the community</"
+"strong> by answering questions of your colleagues. If you do not wish to "
+"receive emails - select 'no email' on all items below.<br/>Updates are only "
+"sent when there is any new activity on selected items."
+
+#: forum/skins/default/templates/users/subscriptions_settings.html:7
+#: forum/skins/zapprotect/templates/users/subscriptions_settings.html:7
+msgid ""
+"\n"
+"    Here you can decide which types of notifications you wish to receive, "
+"and their frequency.<br />\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions_settings.html:11
+#: forum/skins/zapprotect/templates/users/subscriptions_settings.html:11
+msgid ""
+"\n"
+"    Currently you have notifications enabled. You can always stop all "
+"notifications without losing your settings and restart them afterwards.<br /"
+">\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions_settings.html:15
+#: forum/skins/zapprotect/templates/users/subscriptions_settings.html:15
+msgid ""
+"\n"
+"    Currently you have notifications disabled. You can enable them by "
+"clicking on the <strong>Start notifications</strong> button below.<br />\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions_settings.html:26
+#: forum/skins/zapprotect/templates/users/subscriptions_settings.html:26
+msgid "Notify me when:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions_settings.html:30
+#: forum/skins/zapprotect/templates/users/subscriptions_settings.html:30
+msgid "A new member joins"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions_settings.html:34
+#: forum/skins/zapprotect/templates/users/subscriptions_settings.html:34
+#, fuzzy
+msgid "A new question is posted"
+msgstr "Tips"
+
+#: forum/skins/default/templates/users/subscriptions_settings.html:38
+#: forum/skins/zapprotect/templates/users/subscriptions_settings.html:38
+msgid "A new question matching my interesting tags is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions_settings.html:42
+#: forum/skins/zapprotect/templates/users/subscriptions_settings.html:42
+msgid "There's an update on one of my subscriptions"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions_settings.html:50
+#: forum/skins/zapprotect/templates/users/subscriptions_settings.html:50
+msgid "Auto subscribe me to:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions_settings.html:55
+#: forum/skins/zapprotect/templates/users/subscriptions_settings.html:55
+#, fuzzy
+msgid "Questions I ask"
+msgstr "Tags"
+
+#: forum/skins/default/templates/users/subscriptions_settings.html:58
+#: forum/skins/zapprotect/templates/users/subscriptions_settings.html:58
+#, fuzzy
+msgid "Questions I answer"
+msgstr "answer"
+
+#: forum/skins/default/templates/users/subscriptions_settings.html:61
+#: forum/skins/zapprotect/templates/users/subscriptions_settings.html:61
+#, fuzzy
+msgid "Questions I comment"
+msgstr "question comment"
+
+#: forum/skins/default/templates/users/subscriptions_settings.html:66
+#: forum/skins/zapprotect/templates/users/subscriptions_settings.html:66
+#, fuzzy
+msgid "Questions I view"
+msgstr "Tags"
+
+#: forum/skins/default/templates/users/subscriptions_settings.html:69
+#: forum/skins/zapprotect/templates/users/subscriptions_settings.html:69
+msgid "All questions matching my interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions_settings.html:72
+#: forum/skins/zapprotect/templates/users/subscriptions_settings.html:72
+msgid "All questions"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions_settings.html:80
+#: forum/skins/zapprotect/templates/users/subscriptions_settings.html:80
+msgid "On my subscriptions, notify me when:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions_settings.html:85
+#: forum/skins/zapprotect/templates/users/subscriptions_settings.html:85
+#, fuzzy
+msgid "An answer is posted"
+msgstr "Tips"
+
+#: forum/skins/default/templates/users/subscriptions_settings.html:88
+#: forum/skins/zapprotect/templates/users/subscriptions_settings.html:88
+msgid "A comment on one of my posts is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions_settings.html:93
+#: forum/skins/zapprotect/templates/users/subscriptions_settings.html:93
+msgid "A comment is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions_settings.html:96
+#: forum/skins/zapprotect/templates/users/subscriptions_settings.html:96
+#, fuzzy
+msgid "An answer is accepted"
+msgstr "answer accepted"
+
+#: forum/skins/default/templates/users/subscriptions_settings.html:104
+#: forum/skins/zapprotect/templates/users/subscriptions_settings.html:104
+msgid "More:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions_settings.html:109
+#: forum/skins/zapprotect/templates/users/subscriptions_settings.html:109
+msgid ""
+"Notify me when someone replies to one of my comments on any post using the "
+"<pre>@username</pre> notation"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions_settings.html:114
+#: forum/skins/zapprotect/templates/users/subscriptions_settings.html:114
+msgid "Send me the daily digest with information about the site activity"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions_settings.html:121
+#: forum/skins/zapprotect/templates/users/subscriptions_settings.html:121
+msgid "Stop notifications"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions_settings.html:123
+#: forum/skins/zapprotect/templates/users/subscriptions_settings.html:123
+msgid "Start notifications"
+msgstr ""
+
+#: forum/skins/default/templates/users/suspend_user.html:4
+#: forum/skins/zapprotect/templates/users/suspend_user.html:4
+msgid "Suspend user"
+msgstr ""
+
+#: forum/skins/default/templates/users/suspend_user.html:8
+#: forum/skins/zapprotect/templates/users/suspend_user.html:8
+#, fuzzy
+msgid "Indefinetly"
+msgstr "Моментално"
+
+#: forum/skins/default/templates/users/suspend_user.html:9
+#: forum/skins/zapprotect/templates/users/suspend_user.html:9
+msgid "For X days"
+msgstr ""
+
+#: forum/skins/default/templates/users/suspend_user.html:15
+#: forum/skins/zapprotect/templates/users/suspend_user.html:15
+msgid "Suspend for"
+msgstr ""
+
+#: forum/skins/default/templates/users/suspend_user.html:15
+#: forum/skins/zapprotect/templates/users/suspend_user.html:15
+msgid "days"
+msgstr ""
+
+#: forum/skins/default/templates/users/suspend_user.html:20
+#: forum/skins/zapprotect/templates/users/suspend_user.html:20
+#, fuzzy
+msgid "Public message"
+msgstr "Вашето съобщение:"
+
+#: forum/skins/default/templates/users/suspend_user.html:26
+#: forum/skins/zapprotect/templates/users/suspend_user.html:26
+msgid "This message will be visible through the user activity log."
+msgstr ""
+
+#: forum/skins/default/templates/users/suspend_user.html:31
+#: forum/skins/zapprotect/templates/users/suspend_user.html:31
+#, fuzzy
+msgid "Private message"
+msgstr "Вашето съобщение:"
+
+#: forum/skins/default/templates/users/suspend_user.html:37
+#: forum/skins/zapprotect/templates/users/suspend_user.html:37
+msgid "If set, only the suspended user will see this message."
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:6
+#: forum/skins/default/templates/users/users.html:23
+#: forum/skins/zapprotect/templates/users/users.html:6
+#: forum/skins/zapprotect/templates/users/users.html:23
+#: forum_modules/exporter/exporter.py:334
+#: forum_modules/exporter/importer.py:300
+msgid "Users"
+msgstr ""
+
+#: forum/skins/default/templates/users/votes.html:15
+#: forum/skins/zapprotect/templates/users/votes.html:15
+#: forum/views/commands.py:72
+msgid "upvote"
+msgstr "плюс"
+
+#: forum/skins/default/templates/users/votes.html:17
+#: forum/skins/zapprotect/templates/users/votes.html:17
+#: forum/views/commands.py:72
+msgid "downvote"
+msgstr "минус"
+
+#: forum/templatetags/extra_tags.py:77
+msgid "reputation points"
+msgstr "karma"
+
+#: forum/templatetags/extra_tags.py:107
+msgid "2 days ago"
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:109
+msgid "yesterday"
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:111
+#, python-format
+msgid "%(hr)d hour ago"
+msgid_plural "%(hr)d hours ago"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/templatetags/extra_tags.py:113
+#, python-format
+msgid "%(min)d min ago"
+msgid_plural "%(min)d mins ago"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/templatetags/extra_tags.py:115
+#, python-format
+msgid "%(sec)d sec ago"
+msgid_plural "%(sec)d secs ago"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/templatetags/node_tags.py:90
+msgid "permanent link"
+msgstr "link"
+
+#: forum/templatetags/node_tags.py:90
+msgid "answer permanent link"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:96
+msgid "retag"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:100
+msgid "reopen"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:102
+msgid "close"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:105
+msgid "report"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:111
+msgid ""
+"report as offensive (i.e containing spam, advertising, malicious text, etc.)"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:115
+#, fuzzy
+msgid "undelete"
+msgstr "[изтрито]"
+
+#: forum/templatetags/node_tags.py:122
+#, fuzzy
+msgid "see revisions"
+msgstr "изберете ревизия"
+
+#: forum/templatetags/node_tags.py:129
+#, fuzzy
+msgid "mark as community wiki"
+msgstr "уики общност"
+
+#: forum/templatetags/node_tags.py:133
+#, fuzzy
+msgid "cancel community wiki"
+msgstr "уики общност"
+
+#: forum/templatetags/node_tags.py:137
+#, fuzzy
+msgid "convert to comment"
+msgstr "post a comment"
+
+#: forum/templatetags/node_tags.py:204
+msgid "posted"
+msgstr "добавено"
+
+#: forum/views/admin.py:116
+#, fuzzy
+msgid "Questions Graph"
+msgstr "Въпроси"
+
+#: forum/views/admin.py:120
+msgid "Users Graph"
+msgstr ""
+
+#: forum/views/admin.py:159
+#, python-format
+msgid "'%s' settings saved succesfully"
+msgstr ""
+
+#: forum/views/admin.py:266
+msgid "Bootstrap mode enabled"
+msgstr ""
+
+#: forum/views/admin.py:280
+msgid "All values reverted to defaults"
+msgstr ""
+
+#: forum/views/admin.py:296
+msgid "All values recalculated"
+msgstr ""
+
+#: forum/views/admin.py:311
+msgid "Maintenance mode enabled"
+msgstr ""
+
+#: forum/views/admin.py:313
+msgid "Settings adjusted"
+msgstr ""
+
+#: forum/views/admin.py:320
+msgid "Your site is now running normally"
+msgstr ""
+
+#: forum/views/admin.py:324
+msgid "Currently down for maintenance. We'll be back soon"
+msgstr ""
+
+#: forum/views/admin.py:384
+msgid "createuser"
+msgstr ""
+
+#: forum/views/admin.py:384
+#, fuzzy
+msgid "Create new user"
+msgstr "Парола <i>(напишете отново)</i>"
+
+#: forum/views/admin.py:399
+#, python-format
+msgid "New user created sucessfully. %s."
+msgstr ""
+
+#: forum/views/admin.py:400
+#, fuzzy, python-format
+msgid "See %s profile"
+msgstr "завършен потребителски профил"
+
+#: forum/views/admin.py:413
+msgid "added_at"
+msgstr ""
+
+#: forum/views/admin.py:414
+msgid "added_at_asc"
+msgstr ""
+
+#: forum/views/admin.py:415
+msgid "author"
+msgstr ""
+
+#: forum/views/admin.py:416
+msgid "author_asc"
+msgstr ""
+
+#: forum/views/admin.py:417
+msgid "score"
+msgstr ""
+
+#: forum/views/admin.py:418
+msgid "score_asc"
+msgstr ""
+
+#: forum/views/admin.py:419
+msgid "act_at"
+msgstr ""
+
+#: forum/views/admin.py:420
+msgid "act_at_asc"
+msgstr ""
+
+#: forum/views/admin.py:421
+msgid "act_by"
+msgstr ""
+
+#: forum/views/admin.py:422
+msgid "act_by_asc"
+msgstr ""
+
+#: forum/views/admin.py:425
+msgid "nodeman"
+msgstr ""
+
+#: forum/views/admin.py:425
+msgid "Bulk management"
+msgstr ""
+
+#: forum/views/admin.py:431
+#, fuzzy
+msgid "filter"
+msgstr "сребро"
+
+#: forum/views/admin.py:444
+msgid "No action performed"
+msgstr ""
+
+#: forum/views/admin.py:451
+msgid "All selected nodes marked as deleted"
+msgstr ""
+
+#: forum/views/admin.py:458
+msgid "All selected nodes undeleted"
+msgstr ""
+
+#: forum/views/admin.py:463
+msgid "bulk close"
+msgstr ""
+
+#: forum/views/admin.py:465
+#, fuzzy
+msgid "Selected questions were closed"
+msgstr "изтрит въпрос"
+
+#: forum/views/admin.py:477
+msgid "All selected nodes deleted"
+msgstr ""
+
+#: forum/views/auth.py:111 forum/views/auth.py:123
+msgid ""
+"Sorry, these login credentials belong to anoother user. Plese terminate your "
+"current session and try again."
+msgstr ""
+
+#: forum/views/auth.py:114
+msgid "You are already logged in with that user."
+msgstr ""
+
+#: forum/views/auth.py:120
+msgid "These login credentials are already associated with your account."
+msgstr ""
+
+#: forum/views/auth.py:129
+msgid "The new credentials are now associated with your account"
+msgstr ""
+
+#: forum/views/auth.py:170
+msgid ""
+"Oops, something went wrong in the middle of this process. Please try again. "
+"Note that you need to have cookies enabled for the authentication to work."
+msgstr ""
+
+#: forum/views/auth.py:186 forum_modules/localauth/views.py:35
+msgid "A welcome email has been sent to your email address. "
+msgstr ""
+
+#: forum/views/auth.py:191
+msgid ""
+"Oops, something went wrong in the middle of this process. Please try again."
+msgstr ""
+
+#: forum/views/auth.py:247
+msgid "An email has been sent with your temporary login key"
+msgstr ""
+
+#: forum/views/auth.py:263
+msgid ""
+"You are logged in with a temporary access key, please take the time to fix "
+"your issue with authentication."
+msgstr ""
+
+#: forum/views/auth.py:279
+msgid "A message with an email validation link was just sent to your address."
+msgstr ""
+
+#: forum/views/auth.py:290
+msgid "Thank you, your email is now validated."
+msgstr ""
+
+#: forum/views/auth.py:315
+#, fuzzy
+msgid "New password set"
+msgstr "Recover password"
+
+#: forum/views/auth.py:319
+msgid "Your password was changed"
+msgstr ""
+
+#: forum/views/auth.py:355
+#, python-format
+msgid "You removed the association with %s"
+msgstr ""
+
+#: forum/views/auth.py:367
+#, python-format
+msgid "Welcome back %s, you are now logged in"
+msgstr ""
+
+#: forum/views/auth.py:381
+#, python-format
+msgid "You have a %s pending submission."
+msgstr ""
+
+#: forum/views/auth.py:382
+#, fuzzy
+msgid "save it"
+msgstr "Запази промените"
+
+#: forum/views/auth.py:383 forum/views/writers.py:264
+#, fuzzy
+msgid "review"
+msgstr "преглеждания"
+
+#: forum/views/auth.py:384 forum/views/writers.py:261
+#, fuzzy
+msgid "cancel"
+msgstr "Откажи"
+
+#: forum/views/auth.py:392
+msgid "Sorry, but this account is suspended"
+msgstr ""
+
+#: forum/views/commands.py:23
+#, python-format
+msgid ""
+"Sorry, but you don't have enough reputation points to %(action)s.<br /"
+">Please check the <a href='%(faq_url)s'>faq</a>"
+msgstr ""
+
+#: forum/views/commands.py:31
+#, python-format
+msgid ""
+"Sorry but you cannot %(action)s your own post.<br />Please check the <a "
+"href='%(faq_url)s'>faq</a>"
+msgstr ""
+
+#: forum/views/commands.py:39
+#, python-format
+msgid ""
+"Sorry but anonymous users cannot %(action)s.<br />Please login or create an "
+"account <a href='%(signin_url)s'>here</a>."
+msgstr ""
+
+#: forum/views/commands.py:47
+#, python-format
+msgid ""
+"Sorry, but you don't have enough %(action)s left for today..<br />The limit "
+"is %(limit)s per day..<br />Please check the <a href='%(faq_url)s'>faq</a>"
+msgstr ""
+
+#: forum/views/commands.py:55
+#, python-format
+msgid ""
+"Sorry, but you cannot %(action)s twice the same post.<br />Please check the "
+"<a href='%(faq_url)s'>faq</a>"
+msgstr ""
+
+#: forum/views/commands.py:87
+#, python-format
+msgid ""
+"Sorry but you cannot cancel a vote after %(ndays)d %(tdays)s from the "
+"original vote"
+msgstr ""
+
+#: forum/views/commands.py:89
+msgid "day"
+msgid_plural "days"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/views/commands.py:111
+#, python-format
+msgid "You have %(nvotes)s %(tvotes)s left today."
+msgstr ""
+
+#: forum/views/commands.py:125 forum/views/commands.py:131
+msgid "flag posts"
+msgstr ""
+
+#: forum/views/commands.py:128
+msgid "flag"
+msgstr ""
+
+#: forum/views/commands.py:136
+msgid "flags"
+msgstr ""
+
+#: forum/views/commands.py:141
+#, python-format
+msgid "You already flagged this post with the following reason: %(reason)s"
+msgstr ""
+
+#: forum/views/commands.py:146 forum/views/commands.py:374
+#, fuzzy
+msgid "Reason is empty"
+msgstr "История на ревизиите"
+
+#: forum/views/commands.py:150
+msgid ""
+"Thank you for your report. A moderator will review your submission shortly."
+msgstr ""
+
+#: forum/views/commands.py:158 forum/views/commands.py:164
+#, fuzzy
+msgid "like comments"
+msgstr "post a comment"
+
+#: forum/views/commands.py:161
+msgid "like"
+msgstr ""
+
+#: forum/views/commands.py:188 forum/views/commands.py:191
+#, fuzzy
+msgid "delete comments"
+msgstr "post a comment"
+
+#: forum/views/commands.py:207
+msgid "mark a question as favorite"
+msgstr ""
+
+#: forum/views/commands.py:233 forum/views/commands.py:491
+#: forum/views/commands.py:502
+msgid "Invalid request"
+msgstr ""
+
+#: forum/views/commands.py:238
+msgid "Comment is empty"
+msgstr ""
+
+#: forum/views/commands.py:241
+#, python-format
+msgid "At least %d characters required on comment body."
+msgstr ""
+
+#: forum/views/commands.py:244
+#, python-format
+msgid "No more than %d characters on comment body."
+msgstr ""
+
+#: forum/views/commands.py:250
+#, fuzzy
+msgid "edit comments"
+msgstr "post a comment"
+
+#: forum/views/commands.py:283 forum/views/commands.py:297
+#, fuzzy
+msgid "accept answers"
+msgstr "oldest"
+
+#: forum/views/commands.py:303
+msgid "Sorry but you cannot accept the answer"
+msgstr ""
+
+#: forum/views/commands.py:312
+#, fuzzy
+msgid "This question already has an accepted answer."
+msgid_plural ""
+"Sorry but this question has reached the limit of accepted answers."
+msgstr[0] "въпроса е отговорен, приет е верен отговор"
+msgstr[1] "въпроса е отговорен, приет е верен отговор"
+
+#: forum/views/commands.py:319
+msgid ""
+"The author of this answer already has an accepted answer in this question."
+msgid_plural ""
+"Sorry but the author of this answer has reached the limit of accepted "
+"answers per question."
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/views/commands.py:334 forum/views/commands.py:337
+msgid "delete posts"
+msgstr ""
+
+#: forum/views/commands.py:360 forum/views/commands.py:369
+#, fuzzy
+msgid "close questions"
+msgstr "последни въпроси"
+
+#: forum/views/commands.py:364
+#, fuzzy
+msgid "reopen questions"
+msgstr "Отвори отново въпроса"
+
+#: forum/views/commands.py:386 forum/views/commands.py:398
+#, fuzzy
+msgid "mark posts as community wiki"
+msgstr "уики общност"
+
+#: forum/views/commands.py:390
+#, fuzzy
+msgid "cancel a community wiki post"
+msgstr "уики общност"
+
+#: forum/views/commands.py:411
+#, python-format
+msgid "Answer by %(uname)s: %(snippet)s..."
+msgstr ""
+
+#: forum/views/commands.py:413
+#, fuzzy
+msgid "Question"
+msgstr "Въпроси"
+
+#: forum/views/commands.py:420 forum/views/commands.py:423
+#, fuzzy
+msgid "convert answers to comments"
+msgstr "коментар на отговора"
+
+#: forum/views/commands.py:428 forum/views/commands.py:431
+msgid "That is an invalid post to put the comment under"
+msgstr ""
+
+#: forum/views/commands.py:446
+msgid "You do not have the correct credentials to preform this action."
+msgstr ""
+
+#: forum/views/decorators.py:73
+msgid ""
+"We're sorry, but an unknown error ocurred.<br />Please try again in a while."
+msgstr ""
+
+#: forum/views/meta.py:62
+msgid "Thanks for the feedback!"
+msgstr ""
+
+#: forum/views/meta.py:70
+msgid "We look forward to hearing your feedback! Please, give it next time :)"
+msgstr ""
+
+#: forum/views/readers.py:44
+#, fuzzy
+msgid "Most <strong>recently updated</strong> questions"
+msgstr " "
+
+#: forum/views/readers.py:45
+#, fuzzy
+msgid "most <strong>recently asked</strong> questions"
+msgstr "вижте често задаваните въпроси"
+
+#: forum/views/readers.py:46
+#, fuzzy
+msgid "most <strong>active</strong> questions in the last 24 hours</strong>"
+msgstr " "
+
+#: forum/views/readers.py:47
+#, fuzzy
+msgid "mostvoted"
+msgstr "отхвърлен"
+
+#: forum/views/readers.py:47
+#, fuzzy
+msgid "most <strong>voted</strong> questions"
+msgstr " "
+
+#: forum/views/readers.py:60 forum/views/readers.py:261
+#: forum/views/users.py:41 forum/views/users.py:52
+msgid "oldest"
+msgstr ""
+
+#: forum/views/readers.py:60 forum/views/users.py:52
+msgid "oldest answers"
+msgstr "най-старите"
+
+#: forum/views/readers.py:60 forum/views/users.py:52
+msgid "oldest answers will be shown first"
+msgstr "най-старите отговори ще бъдат показани първи"
+
+#: forum/views/readers.py:61 forum/views/users.py:53
+msgid "newest answers"
+msgstr "най-новите"
+
+#: forum/views/readers.py:61 forum/views/users.py:53
+msgid "newest answers will be shown first"
+msgstr "най-новите отговори ще бъдат показани първи"
+
+#: forum/views/readers.py:62 forum/views/users.py:54
+msgid "popular answers"
+msgstr "с най-много гласове"
+
+#: forum/views/readers.py:62 forum/views/users.py:54
+msgid "most voted answers will be shown first"
+msgstr "отговорите с най-много гласове ще бъдат показани първи"
+
+#: forum/views/readers.py:68 forum/views/users.py:42
+#, fuzzy
+msgid "name"
+msgstr "по име"
+
+#: forum/views/readers.py:68
+msgid "by name"
+msgstr "по име"
+
+#: forum/views/readers.py:68
+msgid "sorted alphabetically"
+msgstr "сортирай по азбучен ред"
+
+#: forum/views/readers.py:69 forum/views/readers.py:70
+#, fuzzy
+msgid "used"
+msgstr "зададено"
+
+#: forum/views/readers.py:69
+msgid "by popularity"
+msgstr "по популярност"
+
+#: forum/views/readers.py:69
+msgid "sorted by frequency of tag use"
+msgstr ""
+
+#: forum/views/readers.py:77
+msgid " - "
+msgstr ""
+
+#: forum/views/readers.py:77
+msgid "latest questions"
+msgstr "последни въпроси"
+
+#: forum/views/readers.py:90
+#, fuzzy
+msgid "unanswered"
+msgstr "неотговорени"
+
+#: forum/views/readers.py:94
+#, fuzzy
+msgid "open questions without an accepted answer"
+msgstr "въпроса е отговорен, приет е верен отговор"
+
+#: forum/views/readers.py:96
+#, fuzzy
+msgid "Unanswered Questions"
+msgstr "Неотговорени въпроси"
+
+#: forum/views/readers.py:106
+#, python-format
+msgid "questions tagged <span class=\"tag\">%(tag)s</span>"
+msgstr ""
+
+#: forum/views/readers.py:108
+#, fuzzy, python-format
+msgid "Questions Tagged With %(tag)s"
+msgstr "още въпроси с таг '%(tagname)s'"
+
+#: forum/views/readers.py:117
+#, fuzzy, python-format
+msgid "Questions asked by %s"
+msgstr "Зададен въпрос"
+
+#: forum/views/readers.py:120
+#, fuzzy, python-format
+msgid "Questions answered by %s"
+msgstr "answer"
+
+#: forum/views/readers.py:127
+#, fuzzy, python-format
+msgid "Questions you subscribed %s"
+msgstr "Tags"
+
+#: forum/views/readers.py:129
+#, fuzzy, python-format
+msgid "Questions subscribed by %s"
+msgstr "махни абонамента ми"
+
+#: forum/views/readers.py:152
+msgid "Questions"
+msgstr "Въпроси"
+
+#: forum/views/readers.py:206 forum/views/readers.py:207
+msgid "ranking"
+msgstr ""
+
+#: forum/views/readers.py:206
+msgid "relevance"
+msgstr ""
+
+#: forum/views/readers.py:206
+#, fuzzy
+msgid "most relevant questions"
+msgstr "ask a question relevant to the CNPROG community"
+
+#: forum/views/readers.py:212 forum/views/readers.py:214
+#, python-format
+msgid "questions matching '%(keywords)s'"
+msgstr ""
+
+#: forum/views/readers.py:362
+#, python-format
+msgid "Revision n. %(rev_number)d"
+msgstr ""
+
+#: forum/views/users.py:39
+#, fuzzy
+msgid "sorted by reputation"
+msgstr "karma"
+
+#: forum/views/users.py:40
+msgid "recent"
+msgstr ""
+
+#: forum/views/users.py:40
+#, fuzzy
+msgid "newest members"
+msgstr "най-новите"
+
+#: forum/views/users.py:41
+msgid "last"
+msgstr ""
+
+#: forum/views/users.py:41
+#, fuzzy
+msgid "oldest members"
+msgstr "най-старите"
+
+#: forum/views/users.py:42
+msgid "by username"
+msgstr ""
+
+#: forum/views/users.py:42
+#, fuzzy
+msgid "sorted by username"
+msgstr "Choose screen name"
+
+#: forum/views/users.py:73
+msgid "Online Users"
+msgstr ""
+
+#: forum/views/users.py:167
+#, fuzzy
+msgid "Profile updated."
+msgstr "Последно обновен"
+
+#: forum/views/users.py:181
+msgid "Only superusers are allowed to alter other users permissions."
+msgstr ""
+
+#: forum/views/users.py:184
+msgid "Only the site owner can remove the super user status from other user."
+msgstr ""
+
+#: forum/views/users.py:206
+msgid "Only superusers are allowed to award reputation points"
+msgstr ""
+
+#: forum/views/users.py:211
+msgid "Invalid number of points to award."
+msgstr ""
+
+#: forum/views/users.py:229
+msgid "Only superusers can suspend other users"
+msgstr ""
+
+#: forum/views/users.py:250
+msgid "Invalid numeric argument for the number of days."
+msgstr ""
+
+#: forum/views/users.py:300
+msgid "overview"
+msgstr ""
+
+#: forum/views/users.py:300
+msgid "user overview"
+msgstr ""
+
+#: forum/views/users.py:332
+msgid "recent activity"
+msgstr ""
+
+#: forum/views/users.py:332
+msgid "recent user activity"
+msgstr ""
+
+#: forum/views/users.py:341
+#, fuzzy
+msgid "karma history"
+msgstr "karma history"
+
+#: forum/views/users.py:341
+#, fuzzy
+msgid "graph of user karma"
+msgstr "Graph of user karma"
+
+#: forum/views/users.py:356
+msgid "user vote record"
+msgstr ""
+
+#: forum/views/users.py:363
+msgid "favorites"
+msgstr ""
+
+#: forum/views/users.py:363
+msgid "questions that user selected as his/her favorite"
+msgstr ""
+
+#: forum/views/users.py:369
+#, fuzzy
+msgid "subscription"
+msgstr "Абонамент"
+
+#: forum/views/users.py:369
+msgid "subscriptions"
+msgstr ""
+
+#: forum/views/users.py:383
+#, fuzzy
+msgid "New subscription settings are now saved"
+msgstr ""
+"<span class='big strong'>Adjust frequency of email updates.</span> Receive "
+"updates on interesting questions by email, <strong><br/>help the community</"
+"strong> by answering questions of your colleagues. If you do not wish to "
+"receive emails - select 'no email' on all items below.<br/>Updates are only "
+"sent when there is any new activity on selected items."
+
+#: forum/views/users.py:389
+msgid "Notifications are now enabled"
+msgstr ""
+
+#: forum/views/users.py:391
+msgid "Notifications are now disabled"
+msgstr ""
+
+#: forum/views/users.py:435
+msgid "preferences"
+msgstr ""
+
+#: forum/views/users.py:442
+msgid "New preferences saved"
+msgstr ""
+
+#: forum/views/writers.py:59
+msgid "uploading images is limited to users with >60 reputation points"
+msgstr "sorry, file uploading requires karma >60"
+
+#: forum/views/writers.py:61
+msgid "allowed file types are 'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'"
+msgstr ""
+
+#: forum/views/writers.py:63
+#, python-format
+msgid "maximum upload file size is %sM"
+msgstr ""
+
+#: forum/views/writers.py:65
+#, python-format
+msgid ""
+"Error uploading file. Please contact the site administrator. Thank you. %s"
+msgstr ""
+
+#: forum/views/writers.py:96
+#, python-format
+msgid "Your question is pending until you %s."
+msgstr ""
+
+#: forum/views/writers.py:97 forum/views/writers.py:246
+#, fuzzy
+msgid "validate your email"
+msgstr "How to validate email and why?"
+
+#: forum/views/writers.py:245
+#, python-format
+msgid "Your answer is pending until you %s."
+msgstr ""
+
+#: forum_modules/akismet/settings.py:7
+msgid "WordPress API key"
+msgstr ""
+
+#: forum_modules/akismet/settings.py:8
+msgid ""
+"Your WordPress API key. You can get one at <a href='http://wordpress."
+"com/'>http://wordpress.com/</a>"
+msgstr ""
+
+#: forum_modules/akismet/settings.py:12
+#, fuzzy
+msgid "Minimum reputation to not have your posts checked"
+msgstr "user karma"
+
+#: forum_modules/akismet/settings.py:13
+msgid ""
+"The minimum reputation a user must have so that when they post a question, "
+"answer or comment it is not checked for spam."
+msgstr ""
+
+#: forum_modules/akismet/startup.py:45
+#, python-format
+msgid "Sorry, but akismet thinks your %s is spam."
+msgstr ""
+
+#: forum_modules/akismet/templates/foundspam.html:3
+msgid "Akismet message"
+msgstr ""
+
+#: forum_modules/akismet/templates/foundspam.html:7
+#, python-format
+msgid "Akismet believes your %(action_name)s is spam."
+msgstr ""
+
+#: forum_modules/akismet/templates/foundspam.html:10
+#, python-format
+msgid ""
+"\n"
+"We're sorry, but Akismet believes your %(action_name)s is spam.<br />\n"
+"If you believe this is an error, please contact the forum administrator.\n"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:16
+#, python-format
+msgid "Asked a question with %s views"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:24
+#, fuzzy
+msgid "Popular Question"
+msgstr "Задайте Вашия въпрос"
+
+#: forum_modules/default_badges/badges.py:30
+#, fuzzy
+msgid "Notable Question"
+msgstr "коментиран въпрос"
+
+#: forum_modules/default_badges/badges.py:35
+#, fuzzy
+msgid "Famous Question"
+msgstr "задай въпрос"
+
+#: forum_modules/default_badges/badges.py:54
+#, python-format
+msgid "Question voted up %s times"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:58
+#, fuzzy
+msgid "Nice Question"
+msgstr "Tags"
+
+#: forum_modules/default_badges/badges.py:63
+#, fuzzy
+msgid "Good Question"
+msgstr "Tags"
+
+#: forum_modules/default_badges/badges.py:68
+#, fuzzy
+msgid "Great Question"
+msgstr "Tags"
+
+#: forum_modules/default_badges/badges.py:77
+#, fuzzy, python-format
+msgid "Answer voted up %s times"
+msgstr "Post Your Answer"
+
+#: forum_modules/default_badges/badges.py:81
+#, fuzzy
+msgid "Nice Answer"
+msgstr "редактиран отговор"
+
+#: forum_modules/default_badges/badges.py:86
+#, fuzzy
+msgid "Good Answer"
+msgstr "най-старите"
+
+#: forum_modules/default_badges/badges.py:91
+#, fuzzy
+msgid "Great Answer"
+msgstr "отговор"
+
+#: forum_modules/default_badges/badges.py:100
+#, python-format
+msgid "Question favorited by %s users"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:108
+#, fuzzy
+msgid "Favorite Question"
+msgstr "редактиран въпрос"
+
+#: forum_modules/default_badges/badges.py:113
+#, fuzzy
+msgid "Stellar Question"
+msgstr "Изпратете Вашия отговор"
+
+#: forum_modules/default_badges/badges.py:119
+msgid "Disciplined"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:120
+#, python-format
+msgid "Deleted own post with score of %s or higher"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:128
+msgid "Peer Pressure"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:129
+#, python-format
+msgid "Deleted own post with score of %s or lower"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:139
+msgid "Critic"
+msgstr "Критичен"
+
+#: forum_modules/default_badges/badges.py:140
+msgid "First down vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:150
+#, fuzzy
+msgid "Supporter"
+msgstr "плюс"
+
+#: forum_modules/default_badges/badges.py:151
+msgid "First up vote"
+msgstr "Първи положителен вот"
+
+#: forum_modules/default_badges/badges.py:168
+msgid "Citizen Patrol"
+msgstr "Граждански Патрул"
+
+#: forum_modules/default_badges/badges.py:169
+msgid "First flagged post"
+msgstr "Първа маркирана публикация"
+
+#: forum_modules/default_badges/badges.py:173
+msgid "Organizer"
+msgstr "Организатор"
+
+#: forum_modules/default_badges/badges.py:174
+msgid "First retag"
+msgstr "Първи ретаг"
+
+#: forum_modules/default_badges/badges.py:178
+#, fuzzy
+msgid "Editor"
+msgstr "Редактор"
+
+#: forum_modules/default_badges/badges.py:179
+msgid "First edit"
+msgstr "Първа редакция"
+
+#: forum_modules/default_badges/badges.py:183
+msgid "Scholar"
+msgstr "Учен"
+
+#: forum_modules/default_badges/badges.py:184
+msgid "First accepted answer on your own question"
+msgstr "Първи приет отговор на Вашия собствен въпрос"
+
+#: forum_modules/default_badges/badges.py:188
+msgid "Cleanup"
+msgstr "Почистване"
+
+#: forum_modules/default_badges/badges.py:189
+msgid "First rollback"
+msgstr "Първо почистване"
+
+#: forum_modules/default_badges/badges.py:195
+msgid "Autobiographer"
+msgstr "Автобиографист"
+
+#: forum_modules/default_badges/badges.py:196
+msgid "Completed all user profile fields"
+msgstr "Попълнил е всички полета на потребителския профил"
+
+#: forum_modules/default_badges/badges.py:209
+msgid "Civic Duty"
+msgstr "Граждански Дълг"
+
+#: forum_modules/default_badges/badges.py:210
+#, python-format
+msgid "Voted %s times"
+msgstr "Гласувал %s пъти"
+
+#: forum_modules/default_badges/badges.py:220
+#, fuzzy
+msgid "Pundit"
+msgstr "Учена глава"
+
+#: forum_modules/default_badges/badges.py:221
+#, python-format
+msgid "Left %s comments"
+msgstr "Остават %s коментара"
+
+#: forum_modules/default_badges/badges.py:231
+msgid "Self Learner"
+msgstr "Самоучка"
+
+#: forum_modules/default_badges/badges.py:232
+#, fuzzy, python-format
+msgid "Answered your own question with at least %s up votes"
+msgstr "Отговорил на собствения си въпрос с поне %s положителни гласа"
+
+#: forum_modules/default_badges/badges.py:244
+msgid "Strunk & White"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:245
+#, python-format
+msgid "Edited %s entries"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:255
+msgid "Student"
+msgstr "Студент"
+
+#: forum_modules/default_badges/badges.py:256
+msgid "Asked first question with at least one up vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:267
+#, fuzzy
+msgid "Teacher"
+msgstr "търсене"
+
+#: forum_modules/default_badges/badges.py:268
+msgid "Answered first question with at least one up vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:280
+msgid "Enlightened"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:281
+#, python-format
+msgid "First answer was accepted with at least %s up votes"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:292
+msgid "Guru"
+msgstr "Гуру"
+
+#: forum_modules/default_badges/badges.py:293
+#, python-format
+msgid "Accepted answer and voted up %s times"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:304
+msgid "Necromancer"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:305
+#, python-format
+msgid ""
+"Answered a question more than %(dif_days)s days later with at least %"
+"(up_votes)s votes"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:317
+msgid "Taxonomist"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:318
+#, python-format
+msgid "Created a tag used by %s questions"
+msgstr "Създаде таг използван от %s въпроса"
+
+#: forum_modules/default_badges/settings.py:6
+msgid "Popular Question views"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:7
+msgid ""
+"\n"
+"Number of question views required to award a Popular Question badge to the "
+"question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:12
+msgid "Notable Question views"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:13
+msgid ""
+"\n"
+"Number of question views required to award a Notable Question badge to the "
+"question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:18
+msgid "Famous Question views"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:19
+msgid ""
+"\n"
+"Number of question views required to award a Famous Question badge to the "
+"question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:24
+msgid "Nice Answer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:25
+msgid ""
+"\n"
+"Number of up votes required to award a Nice Answer badge to the answer "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:30
+#, fuzzy
+msgid "Nice Question up votes"
+msgstr "Tags"
+
+#: forum_modules/default_badges/settings.py:31
+msgid ""
+"\n"
+"Number of up votes required to award a Nice Question badge to the question "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:36
+msgid "Good Answer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:37
+msgid ""
+"\n"
+"Number of up votes required to award a Good Answer badge to the answer "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:42
+#, fuzzy
+msgid "Good Question up votes"
+msgstr "Tags"
+
+#: forum_modules/default_badges/settings.py:43
+msgid ""
+"\n"
+"Number of up votes required to award a Good Question badge to the question "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:48
+msgid "Great Answer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:49
+msgid ""
+"\n"
+"Number of up votes required to award a Great Answer badge to the answer "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:54
+#, fuzzy
+msgid "Great Question up votes"
+msgstr "Tags"
+
+#: forum_modules/default_badges/settings.py:55
+msgid ""
+"\n"
+"Number of up votes required to award a Great Question badge to the question "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:60
+msgid "Favorite Question favorite count"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:61
+msgid ""
+"\n"
+"How many times a question needs to be favorited by other users to award a "
+"Favorite Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:66
+msgid "Stellar Question favorite count"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:67
+msgid ""
+"\n"
+"How many times a question needs to be favorited by other users to award a "
+"Stellar Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:72
+msgid "Disciplined minimum score"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:73
+msgid ""
+"\n"
+"Minimum score a question needs to have to award the Disciplined badge to an "
+"author of a question who deletes it.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:78
+msgid "Peer Pressure maximum score"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:79
+msgid ""
+"\n"
+"Maximum score a question needs to have to award the Peer Pressure badge to "
+"an author of a question who deletes it.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:84
+msgid "Civic Duty votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:85
+msgid ""
+"\n"
+"Number of votes an user needs to cast to be awarded the Civic Duty badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:90
+msgid "Pundit number of comments"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:91
+msgid ""
+"\n"
+"Number of comments an user needs to post to be awarded the Pundit badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:96
+msgid "Self Learner up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:97
+msgid ""
+"\n"
+"Number of up votes an answer from the question author needs to have for the "
+"author to be awarded the Self Learner badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:102
+msgid "Strunk and White updates"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:103
+msgid ""
+"\n"
+"Number of question or answer updates an user needs to make to be awarded the "
+"Strunk & White badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:108
+msgid "Enlightened up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:109
+msgid ""
+"\n"
+"Number of up votes an accepted answer needs to have for the author to be "
+"awarded the Enlightened badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:114
+msgid "Guru up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:115
+msgid ""
+"\n"
+"Number of up votes an accepted answer needs to have for the author to be "
+"awarded the Guru badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:120
+msgid "Necromancer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:121
+msgid ""
+"\n"
+"Number of up votes an answer needs to have for the author to be awarded the "
+"Necromancer badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:126
+msgid "Necromancer difference in days"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:127
+msgid ""
+"\n"
+"Difference in days betwen the posted date of a question and an answer for "
+"the answer author to be awarded the Necromancer badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:132
+msgid "Taxonomist usage count"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:133
+msgid ""
+"\n"
+"How many usages a tag needs to have for the tag creator to be awarded the "
+"Taxonomist badge. \n"
+msgstr ""
+
+#: forum_modules/exporter/exporter.py:139
+msgid "Compressing xml files"
+msgstr ""
+
+#: forum_modules/exporter/exporter.py:146
+msgid "Importing uploaded files"
+msgstr ""
+
+#: forum_modules/exporter/exporter.py:151
+msgid "Importing skins folder"
+msgstr ""
+
+#: forum_modules/exporter/exporter.py:155
+msgid "Writing inf file."
+msgstr ""
+
+#: forum_modules/exporter/exporter.py:191
+msgid "Saving backup file"
+msgstr ""
+
+#: forum_modules/exporter/exporter.py:225
+#: forum_modules/exporter/importer.py:214
+msgid "Queued"
+msgstr ""
+
+#: forum_modules/exporter/exporter.py:228
+#: forum_modules/exporter/importer.py:217
+#, fuzzy
+msgid "Starting"
+msgstr "интересно"
+
+#: forum_modules/exporter/exporter.py:249
+#, python-format
+msgid "Exporting %s"
+msgstr ""
+
+#: forum_modules/exporter/exporter.py:250
+msgid "Exporting"
+msgstr ""
+
+#: forum_modules/exporter/exporter.py:254
+msgid "Writing temp file"
+msgstr ""
+
+#: forum_modules/exporter/exporter.py:255
+#, python-format
+msgid "Writing %s temp file"
+msgstr ""
+
+#: forum_modules/exporter/exporter.py:260
+#: forum_modules/exporter/exporter.py:278
+#: forum_modules/exporter/importer.py:244
+#, fuzzy
+msgid "Done"
+msgstr "бронз"
+
+#: forum_modules/exporter/exporter.py:272
+msgid "Compressing files"
+msgstr ""
+
+#: forum_modules/exporter/exporter.py:391
+#: forum_modules/exporter/importer.py:367
+#, fuzzy
+msgid "Nodes"
+msgstr "гласове"
+
+#: forum_modules/exporter/exporter.py:436
+#: forum_modules/exporter/importer.py:440
+#, fuzzy
+msgid "Actions"
+msgstr "Местоположение"
+
+#: forum_modules/exporter/exporter.py:482
+#: forum_modules/exporter/importer.py:509
+#, fuzzy
+msgid "Awards"
+msgstr "all badges"
+
+#: forum_modules/exporter/exporter.py:490
+#: forum_modules/exporter/importer.py:528
+msgid "Settings"
+msgstr ""
+
+#: forum_modules/exporter/forms.py:5
+msgid "Anonymized data"
+msgstr ""
+
+#: forum_modules/exporter/forms.py:5
+msgid "Don't export user data and make all content anonymous"
+msgstr ""
+
+#: forum_modules/exporter/forms.py:6
+msgid "Uploaded files"
+msgstr ""
+
+#: forum_modules/exporter/forms.py:6
+msgid "Include uploaded files in the backup"
+msgstr ""
+
+#: forum_modules/exporter/forms.py:7
+msgid "Skins folder"
+msgstr ""
+
+#: forum_modules/exporter/forms.py:7
+msgid "Include skins folder in the backup"
+msgstr ""
+
+#: forum_modules/exporter/importer.py:238
+#, python-format
+msgid "Importing %s"
+msgstr ""
+
+#: forum_modules/exporter/importer.py:239
+msgid "Importing"
+msgstr ""
+
+#: forum_modules/exporter/settings.py:7
+msgid "Exporter settings"
+msgstr ""
+
+#: forum_modules/exporter/settings.py:7
+msgid "Data export settings"
+msgstr ""
+
+#: forum_modules/exporter/settings.py:10
+msgid "Backups storage"
+msgstr ""
+
+#: forum_modules/exporter/settings.py:11
+msgid "A folder to keep your backups organized."
+msgstr ""
+
+#: forum_modules/exporter/urls.py:8 forum_modules/exporter/urls.py:10
+#: forum_modules/exporter/urls.py:12
+msgid "exporter/"
+msgstr ""
+
+#: forum_modules/exporter/urls.py:8
+msgid "state/"
+msgstr ""
+
+#: forum_modules/exporter/urls.py:9
+msgid "running/"
+msgstr ""
+
+#: forum_modules/exporter/urls.py:10
+#, fuzzy
+msgid "download/"
+msgstr "отхвърлен"
+
+#: forum_modules/exporter/urls.py:12
+msgid "import/"
+msgstr ""
+
+#: forum_modules/exporter/views.py:20 forum_modules/exporter/views.py:68
+msgid "exporter"
+msgstr ""
+
+#: forum_modules/exporter/views.py:20
+msgid "XML data export"
+msgstr ""
+
+#: forum_modules/exporter/templates/exporter.html:6
+#: forum_modules/exporter/templates/running.html:6
+msgid "XML data exporter"
+msgstr ""
+
+#: forum_modules/exporter/templates/exporter.html:9
+#: forum_modules/exporter/templates/running.html:9
+msgid "Export database to XML format"
+msgstr ""
+
+#: forum_modules/exporter/templates/exporter.html:14
+msgid "Available backups"
+msgstr ""
+
+#: forum_modules/exporter/templates/exporter.html:25
+msgid "Start new backup"
+msgstr ""
+
+#: forum_modules/exporter/templates/exporter.html:31
+msgid "Start"
+msgstr ""
+
+#: forum_modules/exporter/templates/importer.html:6
+#: forum_modules/exporter/templates/running.html:6
+msgid "XML data importer"
+msgstr ""
+
+#: forum_modules/exporter/templates/importer.html:9
+msgid "Import data from dump file"
+msgstr ""
+
+#: forum_modules/exporter/templates/running.html:9
+msgid "Restore data from a previouus export"
+msgstr ""
+
+#: forum_modules/exporter/templates/running.html:60
+msgid "Skiped"
+msgstr ""
+
+#: forum_modules/exporter/templates/running.html:96
+msgid "Your backup is ready to be downloaded."
+msgstr ""
+
+#: forum_modules/exporter/templates/running.html:99
+msgid "All data sucessfully imported."
+msgstr ""
+
+#: forum_modules/exporter/templates/running.html:104
+msgid "An error has occurred during de export proccess"
+msgstr ""
+
+#: forum_modules/exporter/templates/running.html:106
+msgid "An error has occurred during de import proccess"
+msgstr ""
+
+#: forum_modules/exporter/templates/running.html:109
+msgid "Please check the log file for a full stack trace."
+msgstr ""
+
+#: forum_modules/exporter/templates/running.html:134
+msgid "Please wait while we prepare your backup file to download."
+msgstr ""
+
+#: forum_modules/exporter/templates/running.html:136
+msgid "Please wait while we import your data."
+msgstr ""
+
+#: forum_modules/exporter/templates/running.html:138
+msgid ""
+"\n"
+"            Started <span id=\"time_started\"></span>\n"
+"        "
+msgstr ""
+
+#: forum_modules/exporter/templates/running.html:142
+msgid "Download file"
+msgstr ""
+
+#: forum_modules/exporter/templates/running.html:147
+msgid "Total progress"
+msgstr ""
+
+#: forum_modules/exporter/templates/running.html:157
+msgid " of "
+msgstr ""
+
+#: forum_modules/facebookauth/authentication.py:31
+msgid "Sorry, your Facebook session has expired, please try again"
+msgstr ""
+
+#: forum_modules/facebookauth/authentication.py:33
+msgid ""
+"The authentication with Facebook connect failed due to an invalid signature"
+msgstr ""
+
+#: forum_modules/facebookauth/authentication.py:35
+msgid ""
+"The authentication with Facebook connect failed, cannot find authentication "
+"tokens"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:75
+msgid "Please enter valid username and password (both are case-sensitive)."
+msgstr ""
+
+#: forum_modules/localauth/forms.py:79
+msgid "Login failed."
+msgstr ""
+
+#: forum_modules/localauth/forms.py:83
+msgid "This user is not a valid user"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:86
+msgid "Please enter username and password"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:88
+msgid "Please enter your password"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:90
+msgid "Please enter user name"
+msgstr ""
+
+#: forum_modules/localauth/urls.py:7
+msgid "local/"
+msgstr ""
+
+#: forum_modules/localauth/templates/loginform.html:4
+#, fuzzy
+msgid "Enter your local user name and password"
+msgstr ""
+"<span class='big strong'>Enter your CNPROG login and password</span><br/"
+"><span class='grey'>(or select your OpenID provider above)</span>"
+
+#: forum_modules/localauth/templates/loginform.html:4
+msgid "or select your external provider above"
+msgstr "или изберете външен доставчик"
+
+#: forum_modules/localauth/templates/loginform.html:8
+#, fuzzy
+msgid "Login name"
+msgstr "Вход"
+
+#: forum_modules/localauth/templates/loginform.html:16
+#, fuzzy
+msgid "Password"
+msgstr "парола"
+
+#: forum_modules/localauth/templates/loginform.html:27
+#, fuzzy
+msgid "Create account"
+msgstr "Регистрация"
+
+#: forum_modules/oauthauth/consumer.py:33
+msgid "Error, the oauth token is not on the server"
+msgstr "Грешка, Auth Token не е на сървъра"
+
+#: forum_modules/oauthauth/consumer.py:38
+msgid "Something went wrong! Auth tokens do not match"
+msgstr "Нещо се обърка! Auth символите не съвпадат"
+
+#: forum_modules/openidauth/consumer.py:51
+msgid "Sorry, but your input is not a valid OpenId"
+msgstr "За съжаление вашия вход не е валиден OpenID"
+
+#: forum_modules/openidauth/consumer.py:125
+msgid "The OpenId authentication request was canceled"
+msgstr "Удостоверяването с OpenID беше отменено"
+
+#: forum_modules/openidauth/consumer.py:127
+msgid "The OpenId authentication failed: "
+msgstr "Удостоверяването с OpenID се провали:"
+
+#: forum_modules/openidauth/consumer.py:129
+msgid "Setup needed"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:131
+msgid "The OpenId authentication failed with an unknown status: "
+msgstr ""
+
+#: forum_modules/openidauth/templates/openidurl.html:7
+msgid "Enter your OpenId Url"
+msgstr ""
+
+#: forum_modules/project_badges/badges.py:9
+msgid "Bug Buster"
+msgstr ""
+
+#: forum_modules/project_badges/badges.py:10
+#, python-format
+msgid "Got %s upvotes in a question tagged with \"bug\""
+msgstr ""
+
+#: forum_modules/recaptcha/formfield.py:20
+msgid "Invalid captcha"
+msgstr ""
+
+#: forum_modules/sximporter/importer.py:137
+#, fuzzy, python-format
+msgid "user-%(id)s"
+msgstr "потребители"
+
+#: forum_modules/sximporter/importer.py:147
+#, python-format
+msgid "user-%(id)s (google)"
+msgstr ""
+
+#: forum_modules/sximporter/importer.py:151
+#, python-format
+msgid "user-%(id)s (yahoo)"
+msgstr ""
+
+#: forum_modules/sximporter/urls.py:8
+msgid "sximporter/"
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:7
+msgid "SX Importer"
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:10
+msgid "Welcome to Stack Exchange dump importer."
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:16
+msgid "Your user id in stack exchange"
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:20
+msgid "Merge users with same user name and email"
+msgstr ""
+
+#: locale/phrases.py:1
+msgid "Test Phrase 1"
+msgstr ""
+
+#: locale/phrases.py:2
+msgid "Test Phrase 2"
+msgstr ""
+
+#: locale/phrases.py:3
+msgid "Test Phrase 3"
+msgstr ""
+
+#: locale/phrases.py:4
+msgid "Test Phrase n"
+msgstr ""
+
+#: rosetta/templates/rosetta/languages.html:4
+#: rosetta/templates/rosetta/languages.html:6
+msgid "Language selection"
+msgstr ""
+
+#: rosetta/templates/rosetta/languages.html:17
+#, fuzzy
+msgid "Application"
+msgstr "Лого"
+
+#: rosetta/templates/rosetta/languages.html:18
+#, fuzzy
+msgid "Progress"
+msgstr "Точки"
+
+#: rosetta/templates/rosetta/languages.html:19
+#, fuzzy
+msgid "Messages"
+msgstr "Вашето съобщение:"
+
+#: rosetta/templates/rosetta/languages.html:20
+#, fuzzy
+msgid "Translated"
+msgstr "обновено"
+
+#: rosetta/templates/rosetta/languages.html:21
+#: rosetta/templates/rosetta/pofile.html:57
+msgid "Fuzzy"
+msgstr ""
+
+#: rosetta/templates/rosetta/languages.html:22
+msgid "Obsolete"
+msgstr ""
+
+#: rosetta/templates/rosetta/languages.html:23
+#, fuzzy
+msgid "File"
+msgstr "сребро"
+
+#: rosetta/templates/rosetta/languages.html:44
+msgid "Nothing to translate!"
+msgstr ""
+
+#: rosetta/templates/rosetta/languages.html:45
+msgid ""
+"You haven't specified any languages in your settings file, or haven't yet "
+"generated a batch of translation catalogs."
+msgstr ""
+
+#: rosetta/templates/rosetta/languages.html:46
+#, python-format
+msgid ""
+"Please refer to <a href=\"%(i18n_doc_link)s\">Django's I18N documentation</"
+"a> for a guide on how to set up internationalization for your project."
+msgstr ""
+
+#: rosetta/templates/rosetta/pofile.html:8
+msgid "Pick another file"
+msgstr ""
+
+#: rosetta/templates/rosetta/pofile.html:9
+msgid "Download this catalog"
+msgstr ""
+
+#: rosetta/templates/rosetta/pofile.html:21
+#, python-format
+msgid "Progress: %(percent_translated)s%%"
+msgstr ""
+
+#: rosetta/templates/rosetta/pofile.html:23
+msgid "File is read-only: download the file when done editing!"
+msgstr ""
+
+#: rosetta/templates/rosetta/pofile.html:24
+msgid ""
+"Some items in your last translation block couldn't be saved: this usually "
+"happens when the catalog file changes on disk after you last loaded it."
+msgstr ""
+
+#: rosetta/templates/rosetta/pofile.html:28
+#, python-format
+msgid "Translate into %(rosetta_i18n_lang_name)s"
+msgstr ""
+
+#: rosetta/templates/rosetta/pofile.html:31
+#, fuzzy
+msgid "Display:"
+msgstr "Дневно"
+
+#: rosetta/templates/rosetta/pofile.html:32
+msgid "Untranslated only"
+msgstr ""
+
+#: rosetta/templates/rosetta/pofile.html:33
+msgid "Translated only"
+msgstr ""
+
+#: rosetta/templates/rosetta/pofile.html:34
+msgid "Fuzzy only"
+msgstr ""
+
+#: rosetta/templates/rosetta/pofile.html:35
+msgid "All"
+msgstr ""
+
+#: rosetta/templates/rosetta/pofile.html:54
+msgid "Original"
+msgstr ""
+
+#: rosetta/templates/rosetta/pofile.html:58
+msgid "Occurrences(s)"
+msgstr ""
+
+#: rosetta/templates/rosetta/pofile.html:82
+msgid "suggest"
+msgstr ""
+
+#: rosetta/templates/rosetta/pofile.html:93
+#, python-format
+msgid "%(more_count)s more"
+msgid_plural "%(more_count)s more"
+msgstr[0] ""
+msgstr[1] ""
+
+#: rosetta/templates/rosetta/pofile.html:105
+msgid "Save and translate next block"
+msgstr ""
+
+#: rosetta/templates/rosetta/pofile.html:109
+#, fuzzy
+msgid "Skip to page:"
+msgstr "обратно на началната страница"
+
+#: rosetta/templates/rosetta/pofile.html:122
+msgid "Displaying:"
+msgstr ""
+
+#: rosetta/templates/rosetta/pofile.html:124
+#, python-format
+msgid "%(hits)s/%(message_number)s message"
+msgid_plural "%(hits)s/%(message_number)s messages"
+msgstr[0] ""
+msgstr[1] ""
+
+#~ msgid "duplicate question"
+#~ msgstr "повтарящ се въпрос"
+
+#~ msgid "question is off-topic or not relevant"
+#~ msgstr "въпроса е извън темата или е нерелевантен"
+
+#~ msgid "too subjective and argumentative"
+#~ msgstr "прекалено субективен и спорен"
+
+#~ msgid "commented answer"
+#~ msgstr "коментиран отговор"
+
+#~ msgid "received award"
+#~ msgstr "получена награда"
+
+#~ msgid "marked best answer"
+#~ msgstr "маркиран за най-добър отговор"
+
+#~ msgid "upvote canceled"
+#~ msgstr "поддръжката е отменена"
+
+#~ msgid "downvote canceled"
+#~ msgstr "отхвърлянето е отменено"
+
+#~ msgid "deleted answer"
+#~ msgstr "изтрит отговор"
+
+#~ msgid "marked offensive"
+#~ msgstr "маркирано за обидно"
+
+#~ msgid "updated tags"
+#~ msgstr "обновени тагове"
+
+#~ msgid "selected favorite"
+#~ msgstr "избрано за любимо"
+
+#~ msgid "email update sent to user"
+#~ msgstr "изпратено е имейл известяване до потребителя"
+
+#~ msgid "question_answered"
+#~ msgstr "отговор"
+
+#~ msgid "answer_accepted"
+#~ msgstr "приет отговор"
+
+#~ msgid "initial version"
+#~ msgstr "първоначална версия"
+
+#~ msgid "Weekly"
+#~ msgstr "Седмично"
+
+#~ msgid "please use 5 tags or less"
+#~ msgstr "моля, използвайте до 5 тага"
+
+#~ msgid "tags must be shorter than 20 characters"
+#~ msgstr "таговете трябва да са по-кратки от 20 символа"
+
+#~ msgid "Automatically accept user's contributions for the email updates"
+#~ msgstr "Автоматично приемай потребителските добавяния за имейл ъпдейтите"
+
+#~ msgid "marked an answer"
+#~ msgstr "маркирано като прочетено"
+
+#~ msgid "commented a question"
+#~ msgstr "списък на всички въпроси"
+
+#~ msgid "edited an answer"
+#~ msgstr "най-старите"
+
+#~ msgid "received badge"
+#~ msgstr "получена точка"
+
+#~ msgid ""
+#~ "the page you tried to visit is protected or you don't have sufficient "
+#~ "points, see"
+#~ msgstr ""
+#~ "страницата е защитена или нямате подходящите права за да я преглеждате"
+
+#~ msgid "this answer has been accepted to be correct"
+#~ msgstr "този въпрос"
+
+#~ msgid "login to post question info"
+#~ msgstr ""
+#~ "<span class=\"strong big\">Вие сте свободни да задавате Вашите въпроси "
+#~ "анонимно</span>. Когато изберете да изпратите публикацията, тя ще бъде "
+#~ "запазена в сесията и след като се оторизирате ще можете да продължите "
+#~ "добавянето. Процеса на регистрация и оторизиране е много прост. Отнема по-"
+#~ "малко от минута."
+
+#~ msgid ""
+#~ "must have valid %(email)s to post, \n"
+#~ "                            see %(email_validation_faq_url)s\n"
+#~ "                            "
+#~ msgstr ""
+#~ "<span class='strong big'>Изглежда, че имейла Ви, %(email)s не е бил "
+#~ "потвърден.</span> За да добавяте информация, трябва да потвърдите имейла "
+#~ "си, можете да намерите повече информация на <a href='%"
+#~ "(email_validation_faq_url)s'>страницата за потвърждение на имейла</a>."
+#~ "<br>Можете да изпратите съобщението си и да потвърдите имейла след това, "
+#~ "но съобщението няма да бъде визуализирано. "
+
+#~ msgid ""
+#~ "Before asking the question - please make sure to use search to see "
+#~ "whether your question has alredy been answered."
+#~ msgstr ""
+#~ "Before you ask - please make sure to search for a similar question. You "
+#~ "can search questions by their title or tags."
+
+#~ msgid "What questions should I avoid asking?"
+#~ msgstr "What kinds of questions should be avoided?"
+
+#~ 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 ""
+#~ "is a <strong>question and answer</strong> site - <strong>it is not a "
+#~ "discussion group</strong>. Please avoid holding debates in your answers "
+#~ "as they tend to dilute the essense of questions and answers. For the "
+#~ "brief discussions please use commenting facility."
+
+#~ msgid ""
+#~ "The reputation system allows users earn the authorization to perform a "
+#~ "variety of moderation tasks."
+#~ msgstr ""
+#~ "Karma system allows users to earn rights to perform a variety of "
+#~ "moderation tasks"
+
+#~ msgid "How does reputation system work?"
+#~ msgstr "How does karma system work?"
+
+#~ msgid "Rep system summary"
+#~ msgstr ""
+#~ "When a question or answer is upvoted, the user who posted them will gain "
+#~ "some points, which are called \"karma points\". These points serve as a "
+#~ "rough measure of the community trust to him/her. Various moderation tasks "
+#~ "are gradually assigned to the users based on those points."
+
+#~ msgid "use tags"
+#~ msgstr "използвай тагове"
+
+#~ msgid ""
+#~ "how to validate email info with %(send_email_key_url)s %(gravatar_faq_url)"
+#~ "s"
+#~ msgstr ""
+#~ "<form style='margin:0;padding:0;' action='%(send_email_key_url)"
+#~ "s'><p><span class=\"bigger strong\">How?</span> If you have just set or "
+#~ "changed your email address - <strong>check your email and click the "
+#~ "included link</strong>.<br>The link contains a key generated specifically "
+#~ "for you. You can also <button style='display:inline' "
+#~ "type='submit'><strong>get a new key</strong></button> and check your "
+#~ "email again.</p></form><span class=\"bigger strong\">Why?</span> Email "
+#~ "validation is required to make sure that <strong>only you can post "
+#~ "messages</strong> on your behalf and to <strong>minimize spam</strong> "
+#~ "posts.<br>With email you can <strong>subscribe for updates</strong> on "
+#~ "the most interesting questions. Also, when you sign up for the first time "
+#~ "- create a unique <a href='%(gravatar_faq_url)s'><strong>gravatar</"
+#~ "strong></a> personal image.</p>"
+
+#~ msgid ""
+#~ "Please ask your question at %(ask_question_url)s, help make our community "
+#~ "better!"
+#~ msgstr ""
+#~ "Please <a href='%(ask_question_url)s'>ask</a> your question, help make "
+#~ "our community better!"
+
+#~ msgid "give feedback"
+#~ msgstr "остави отзив"
+
+#~ msgid "close date %(closed_at)s"
+#~ msgstr "дата на затваряне %(closed_at)s"
+
+#~ msgid "question tips"
+#~ msgstr "Съвети"
+
+#~ msgid "up to 5 tags, less than 20 characters each"
+#~ msgstr "до 5 тага, с дължина до 20 символа всеки"
+
+#~ msgid "all tags - make this empty in english"
+#~ msgstr "всички тагове"
+
+#~ msgid "Sorry, looks like we have some errors:"
+#~ msgstr "Изглежда е станала грешка:"
+
+#~ msgid "Screen name label"
+#~ msgstr ""
+#~ "<strong>Публично име</strong> (<i>ще бъде показано на останалите</i>)"
+
+#~ msgid "Email address label"
+#~ msgstr ""
+#~ "<strong>Имейл адрес</strong> (<i><strong>няма<strong> да бъде споделяно с "
+#~ "никой, трябва да бъде валиден</i>)"
+
+#~ msgid "To make use of the Forum, please follow the link below:"
+#~ msgstr "За да използвате Zapprotect Q&A, използвайте следния линк:"
+
+#~ msgid ""
+#~ "Sincerely,<br />\n"
+#~ "    Forum Administrator"
+#~ msgstr ""
+#~ "Sincerely,\n"
+#~ "Q&A Forum Administrator"
+
+#~ msgid "Click to sign in through any of these services."
+#~ msgstr ""
+#~ "<p><span class=\"big strong\">Please select your favorite login method "
+#~ "below.</span></p><p><font color=\"gray\">External login services use <a "
+#~ "href=\"http://openid.net\"><b>OpenID</b></a> technology, where your "
+#~ "password always stays confidential between you and your login provider "
+#~ "and you don't have to remember another one. CNPROG option requires your "
+#~ "login name and password entered here.</font></p>"
+
+#~ msgid "Traditional signup info"
+#~ msgstr ""
+#~ "<span class='strong big'>If you prefer, create your forum login name and "
+#~ "password here. However</span>, please keep in mind that we also support "
+#~ "<strong>OpenID</strong> login method. With <strong>OpenID</strong> you "
+#~ "can simply reuse your external login (e.g. Gmail or AOL) without ever "
+#~ "sharing your login details with anyone and having to remember yet another "
+#~ "password."
+
+#~ msgid " add comment"
+#~ msgstr "post a comment"
+
+#~ msgid "On question "
+#~ msgstr "Tips"
+
+#~ msgid ""
+#~ "\n"
+#~ "                    %(comment_count)s new comment%"
+#~ "(comment_count_pluralize)s\n"
+#~ "                "
+#~ msgstr ""
+#~ "\n"
+#~ "(one comment)"
+
+#~ msgid ""
+#~ "\n"
+#~ "                    Posted by %(author_name)s in %(question_time)s\n"
+#~ "                "
+#~ msgstr ""
+#~ "\n"
+#~ "<div class=\"questions-count\">%(q_num)s</div><p>question</p>"
+
+#~ msgid "avatar, see %(gravatar_faq_url)s"
+#~ msgstr "<a href='%(gravatar_faq_url)s'>gravatar</a>"
+
+#~ msgid "casted votes"
+#~ msgstr "votes"
+
+#~ msgid "Questions sorted by <strong>number of responses</strong>."
+#~ msgstr "Questions sorted by the <strong>number of answers</strong>."
+
+#~ msgid "user reputation in the community"
+#~ msgstr "user karma"
+
+#~ msgid "profile - user reputation"
+#~ msgstr "Profile - User's Karma"
+
+#~ msgid "profile - subscriptions"
+#~ msgstr "Profile - User's Karma"
+
+#~ msgid "email update message subject"
+#~ msgstr "news from Q&A forum"
+
+#~ msgid "%(name)s, this is an update message header for a question"
+#~ msgid_plural ""
+#~ "%(name)s, this is an update message header for %(num)d questions"
+#~ msgstr[0] ""
+#~ "<p>Dear %(name)s,</p></p>The following question has been updated on the "
+#~ "Q&A forum:</p>"
+#~ msgstr[1] ""
+#~ "<p>Dear %(name)s,</p><p>The following %(num)d questions have been updated "
+#~ "on the Q&A forum:</p>"
+
+#~ msgid ""
+#~ "go to %(link)s to change frequency of email updates or %(email)s "
+#~ "administrator"
+#~ msgstr ""
+#~ "<p>Please remember that you can always <a href='%(link)s'>adjust</a> "
+#~ "frequency of the email updates or turn them off entirely.<br/>If you "
+#~ "believe that this message was sent in an error, please email about it the "
+#~ "forum administrator at %(email)s.</p><p>Sincerely,</p><p>Your friendly "
+#~ "Q&A forum server.</p>"
+
+#~ msgid "Account: change password"
+#~ msgstr "Change your password"
+
+#~ msgid "list of unanswered questions"
+#~ msgstr "unanswered questions"
+
+#~ msgid "Notify me once a day when there are any new answers"
+#~ msgstr ""
+#~ "<strong>Notify me</strong> once a day by email when there are any new "
+#~ "answers or updates"
+
+#~ msgid "Notify me weekly when there are any new answers"
+#~ msgstr ""
+#~ "<strong>Notify me</strong> weekly when there are any new answers or "
+#~ "updates"
+
+#~ msgid ""
+#~ "\n"
+#~ "                You can always adjust frequency of email updates from "
+#~ "your %(profile_url)s\n"
+#~ "                "
+#~ msgstr ""
+#~ "\n"
+#~ "(note: you can always <a href='%(profile_url)s?"
+#~ "sort=email_subscriptions'>adjust frequency</a> of email updates)"
+
+#~ msgid ""
+#~ "\n"
+#~ "                    have total %(q_num)s questions containing %"
+#~ "(searchtitle)s in full text\n"
+#~ "                    "
+#~ msgid_plural ""
+#~ "\n"
+#~ "                    have total %(q_num)s questions containing %"
+#~ "(searchtitle)s in full text\n"
+#~ "                    "
+#~ msgstr[0] ""
+#~ "\n"
+#~ "<div class=\"questions-count\">%(q_num)s</div><p>question containing "
+#~ "<strong><span class=\"darkred\">%(searchtitle)s</span></strong></p>"
+#~ msgstr[1] ""
+#~ "\n"
+#~ "<div class=\"questions-count\">%(q_num)s</div><p>questions containing "
+#~ "<strong><span class=\"darkred\">%(searchtitle)s</span></strong></p>"
+
+#~ msgid "Most recently answered ones are shown first."
+#~ msgstr "<strong>Most recently answered</strong> questions are shown first."
+
+#~ msgid "change %(email)s info"
+#~ msgstr ""
+#~ "<span class=\"strong big\">Enter your new email into the box below</span> "
+#~ "if you'd like to use another email for <strong>update subscriptions</"
+#~ "strong>.<br>Currently you are using <strong>%(email)s</strong>"
+
+#~ msgid "here is why email is required, see %(gravatar_faq_url)s"
+#~ msgstr ""
+#~ "<span class='strong big'>Please enter your email address in the box below."
+#~ "</span> Valid email address is required on this Q&amp;A forum. If you "
+#~ "like, you can <strong>receive updates</strong> on interesting questions "
+#~ "or entire forum via email. Also, your email is used to create a unique <a "
+#~ "href='%(gravatar_faq_url)s'><strong>gravatar</strong></a> image for your "
+#~ "account. Email addresses are never shown or otherwise shared with anybody "
+#~ "else."
+
+#~ msgid "validate %(email)s info or go to %(change_email_url)s"
+#~ msgstr ""
+#~ "<span class=\"strong big\">An email with a validation link has been sent "
+#~ "to %(email)s.</span> Please <strong>follow the emailed link</strong> with "
+#~ "your web browser. Email validation is necessary to help insure the proper "
+#~ "use of email on <span class=\"orange\">Q&amp;A</span>. If you would like "
+#~ "to use <strong>another email</strong>, please <a href='%(change_email_url)"
+#~ "s'><strong>change it again</strong></a>."
+
+#~ msgid "old %(email)s kept, if you like go to %(change_email_url)s"
+#~ msgstr ""
+#~ "<span class=\"strong big\">Your email address %(email)s has not been "
+#~ "changed.</span> If you decide to change it later - you can always do it "
+#~ "by editing it in your user profile or by using the <a href='%"
+#~ "(change_email_url)s'><strong>previous form</strong></a> again."
+
+#~ msgid "your current %(email)s can be used for this"
+#~ msgstr ""
+#~ "<span class='big strong'>Your email address is now set to %(email)s.</"
+#~ "span> Updates on the questions that you like most will be sent to this "
+#~ "address. Email notifications are sent once a day or less frequently - "
+#~ "only when there are any news."
+
+#~ msgid "thanks for verifying email"
+#~ msgstr ""
+#~ "<span class=\"big strong\">Thank you for verifying your email!</span> Now "
+#~ "you can <strong>ask</strong> and <strong>answer</strong> questions. Also "
+#~ "if you find a very interesting question you can <strong>subscribe for the "
+#~ "updates</strong> - then will be notified about changes <strong>once a "
+#~ "day</strong> or less frequently."
+
+#~ msgid "email key not sent"
+#~ msgstr "Validation email not sent"
+
+#~ msgid "email key not sent %(email)s change email here %(change_link)s"
+#~ msgstr ""
+#~ "<span class='big strong'>Your current email address %(email)s has been "
+#~ "validated before</span> so the new key was not sent. You can <a href='%"
+#~ "(change_link)s'>change</a> email used for update subscriptions if "
+#~ "necessary."
+
+#~ msgid "register new %(provider)s account info, see %(gravatar_faq_url)s"
+#~ msgstr ""
+#~ "<p><span class=\"big strong\">You are here for the first time with your %"
+#~ "(provider)s login.</span> Please create your <strong>screen name</strong> "
+#~ "and save your <strong>email</strong> address. Saved email address will "
+#~ "let you <strong>subscribe for the updates</strong> on the most "
+#~ "interesting questions and will be used to create and retrieve your unique "
+#~ "avatar image - <a href='%(gravatar_faq_url)s'><strong>gravatar</strong></"
+#~ "a>.</p>"
+
+#~ msgid ""
+#~ "%(username)s already exists, choose another name for \n"
+#~ "                            %(provider)s. Email is required too, see %"
+#~ "(gravatar_faq_url)s\n"
+#~ "                        "
+#~ msgstr ""
+#~ "<p><span class='strong big'>Oops... looks like screen name %(username)s "
+#~ "is already used in another account.</span></p><p>Please choose another "
+#~ "screen name to use with your %(provider)s login. Also, a valid email "
+#~ "address is required on the <span class='orange'>Q&amp;A</span> forum. "
+#~ "Your email is used to create a unique <a href='%(gravatar_faq_url)"
+#~ "s'><strong>gravatar</strong></a> image for your account. If you like, you "
+#~ "can <strong>receive updates</strong> on the interesting questions or "
+#~ "entire forum by email. Email addresses are never shown or otherwise "
+#~ "shared with anybody else.</p>"
+
+#~ msgid ""
+#~ "register new external %(provider)s account info, see %(gravatar_faq_url)s"
+#~ msgstr ""
+#~ "<p><span class=\"big strong\">You are here for the first time with your %"
+#~ "(provider)s login.</span></p><p>You can either keep your <strong>screen "
+#~ "name</strong> the same as your %(provider)s login name  or choose some "
+#~ "other nickname.</p><p>Also, please save a valid <strong>email</strong> "
+#~ "address. With the email you can <strong>subscribe for the updates</"
+#~ "strong> on the most interesting questions. Email address is also used to "
+#~ "create and retrieve your unique avatar image - <a href='%"
+#~ "(gravatar_faq_url)s'><strong>gravatar</strong></a>.</p>"
+
+#~ msgid "register new Facebook connect account info, see %(gravatar_faq_url)s"
+#~ msgstr ""
+#~ "<p><span class=\"big strong\">You are here for the first time with your "
+#~ "Facebook login.</span> Please create your <strong>screen name</strong> "
+#~ "and save your <strong>email</strong> address. Saved email address will "
+#~ "let you <strong>subscribe for the updates</strong> on the most "
+#~ "interesting questions and will be used to create and retrieve your unique "
+#~ "avatar image - <a href='%(gravatar_faq_url)s'><strong>gravatar</strong></"
+#~ "a>.</p>"
+
+#~ msgid "password recovery information"
+#~ msgstr ""
+#~ "<span class='big strong'>Forgot you password? No problems - just get a "
+#~ "new one!</span><br/>Please follow the following steps:<br/>&bull; submit "
+#~ "your user name below and check your email<br/>&bull; <strong>follow the "
+#~ "activation link</strong> for the new password - sent to you by email and "
+#~ "login with the suggested password<br/>&bull; at this you might want to "
+#~ "change your password to something you can remember better"
+
+#~ msgid "Reset password"
+#~ msgstr "Send me a new password"
+
+#~ msgid ""
+#~ "email explanation how to use new %(password)s for %(username)s\n"
+#~ "with the %(key_link)s"
+#~ msgstr ""
+#~ "To change your password, please follow these steps:\n"
+#~ "* visit this link: %(key_link)s\n"
+#~ "* login with user name %(username)s and password %(password)s\n"
+#~ "* go to your user profile and set the password to something you can "
+#~ "remember"
+
+#~ msgid ""
+#~ "\n"
+#~ "                Your answer to %(title)s %(summary)s will be posted once "
+#~ "you log in\n"
+#~ "                "
+#~ msgstr ""
+#~ "\n"
+#~ "<span class=\"strong big\">Your answer to </span> <i>\"<strong>%(title)s</"
+#~ "strong> %(summary)s...\"</i> <span class=\"strong big\">is saved and will "
+#~ "be posted once you log in.</span>"
+
+#~ msgid ""
+#~ "Your question \n"
+#~ "                %(title)s %(summary)s will be posted once you log in\n"
+#~ "                "
+#~ msgstr ""
+#~ "<span class=\"strong big\">Your question</span> <i>\"<strong>%(title)s</"
+#~ "strong> %(summary)s...\"</i> <span class=\"strong big\">is saved and will "
+#~ "be posted once you log in.</span>"
+
+#~ msgid "Enter your <span id=\"enter_your_what\">Provider user name</span>"
+#~ msgstr ""
+#~ "<span class=\"big strong\">Enter your </span><span id=\"enter_your_what\" "
+#~ "class='big strong'>Provider user name</span><br/><span class='grey'>(or "
+#~ "select another login method above)</span>"
+
+#~ msgid ""
+#~ "Enter your <a class=\"openid_logo\" href=\"http://openid.net\">OpenID</a> "
+#~ "web address"
+#~ msgstr ""
+#~ "<span class=\"big strong\">Enter your <a class=\"openid_logo\" href="
+#~ "\"http://openid.net\">OpenID</a> web address</span><br/><span "
+#~ "class='grey'>(or choose another login method above)</span>"
+
+#~ msgid "subscription saved, %(email)s needs validation, see %(details_url)s"
+#~ msgstr ""
+#~ "Your subscription is saved, but email address %(email)s needs to be "
+#~ "validated, please see <a href='%(details_url)s'>more details here</a>"
+
+#~ msgid "Incorrect username."
+#~ msgstr "sorry, there is no such user name"
+
+#~ msgid "your email needs to be validated see %(details_url)s"
+#~ msgstr ""
+#~ "Your email needs to be validated. Please see details <a "
+#~ "id='validate_email_alert' href='%(details_url)s'>here</a>."
+
+#~ msgid "Email verification subject line"
+#~ msgstr "Verification Email from Q&A forum"
+
+#~ msgid "first time greeting with %(url)s"
+#~ msgstr "Hello and welcome to OSQA - <a href='%(url)s'>please join us</a>!"
+
+#~ msgid ""
+#~ "\n"
+#~ "\t\t\t\thave total %(q_num)s questions\n"
+#~ "\t\t\t\t"
+#~ msgid_plural ""
+#~ "\n"
+#~ "\t\t\t\thave total %(q_num)s questions\n"
+#~ "\t\t\t\t"
+#~ msgstr[0] ""
+#~ "\n"
+#~ "<div class=\"questions-count\">%(q_num)s</div><p>question</p>"
+#~ msgstr[1] ""
+#~ "\n"
+#~ "<div class=\"questions-count\">%(q_num)s</div><p>questions</p>"
diff --git a/forum/modules/template_loader.py/locale/de/LC_MESSAGES/django.mo b/forum/modules/template_loader.py/locale/de/LC_MESSAGES/django.mo
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/forum/modules/template_loader.py/locale/de/LC_MESSAGES/django.po b/forum/modules/template_loader.py/locale/de/LC_MESSAGES/django.po
new file mode 100644 (file)
index 0000000..1b2e4f7
--- /dev/null
@@ -0,0 +1,4428 @@
+#: forum/const.py:8
+msgid "duplicate question"
+msgstr ""
+
+#: forum/const.py:9
+msgid "question is off-topic or not relevant"
+msgstr ""
+
+#: forum/const.py:10
+msgid "too subjective and argumentative"
+msgstr ""
+
+#: forum/const.py:11
+msgid "is not an answer to the question"
+msgstr ""
+
+#: forum/const.py:12
+msgid "the question is answered, right answer was accepted"
+msgstr ""
+
+#: forum/const.py:13
+msgid "problem is not reproducible or outdated"
+msgstr ""
+
+#: forum/const.py:14
+msgid "question contains offensive inappropriate, or malicious remarks"
+msgstr ""
+
+#: forum/const.py:15
+msgid "spam or advertising"
+msgstr ""
+
+#: forum/const.py:71 forum/skins/default/templates/osqaadmin/index.html:21
+msgid "question"
+msgstr ""
+
+#: forum/const.py:72 forum/skins/default/templates/book.html:110
+#: forum/skins/default/templates/osqaadmin/index.html:26
+msgid "answer"
+msgstr ""
+
+#: forum/const.py:73
+msgid "commented question"
+msgstr ""
+
+#: forum/const.py:74
+msgid "commented answer"
+msgstr ""
+
+#: forum/const.py:75
+msgid "edited question"
+msgstr ""
+
+#: forum/const.py:76
+msgid "edited answer"
+msgstr ""
+
+#: forum/const.py:77
+msgid "received award"
+msgstr ""
+
+#: forum/const.py:78
+msgid "marked best answer"
+msgstr ""
+
+#: forum/const.py:79
+msgid "upvoted"
+msgstr ""
+
+#: forum/const.py:80
+msgid "downvoted"
+msgstr ""
+
+#: forum/const.py:81
+msgid "upvote canceled"
+msgstr ""
+
+#: forum/const.py:82
+msgid "downvote canceled"
+msgstr ""
+
+#: forum/const.py:83
+msgid "deleted question"
+msgstr ""
+
+#: forum/const.py:84
+msgid "deleted answer"
+msgstr ""
+
+#: forum/const.py:85
+msgid "marked offensive"
+msgstr ""
+
+#: forum/const.py:86
+msgid "updated tags"
+msgstr ""
+
+#: forum/const.py:87
+msgid "selected favorite"
+msgstr ""
+
+#: forum/const.py:88
+msgid "completed user profile"
+msgstr ""
+
+#: forum/const.py:89
+msgid "email update sent to user"
+msgstr ""
+
+#: forum/const.py:93
+msgid "question_answered"
+msgstr ""
+
+#: forum/const.py:94
+msgid "question_commented"
+msgstr ""
+
+#: forum/const.py:95
+msgid "answer_commented"
+msgstr ""
+
+#: forum/const.py:96
+msgid "answer_accepted"
+msgstr ""
+
+#: forum/const.py:100
+msgid "[closed]"
+msgstr ""
+
+#: forum/const.py:101
+msgid "[deleted]"
+msgstr ""
+
+#: forum/const.py:102
+msgid "initial version"
+msgstr ""
+
+#: forum/const.py:103
+msgid "retagged"
+msgstr ""
+
+#: forum/const.py:111
+msgid "Instantly"
+msgstr ""
+
+#: forum/const.py:112
+msgid "Daily"
+msgstr ""
+
+#: forum/const.py:113
+msgid "Weekly"
+msgstr ""
+
+#: forum/const.py:114
+msgid "No notifications"
+msgstr ""
+
+#: forum/feed.py:18
+msgid " - "
+msgstr ""
+
+#: forum/feed.py:18
+msgid "latest questions"
+msgstr ""
+
+#: forum/forms.py:21 forum/skins/default/templates/answer_edit_tips.html:35
+#: forum/skins/default/templates/answer_edit_tips.html:39
+#: forum/skins/default/templates/question_edit_tips.html:37
+#: forum/skins/default/templates/question_edit_tips.html:42
+msgid "title"
+msgstr ""
+
+#: forum/forms.py:22
+msgid "please enter a descriptive title for your question"
+msgstr ""
+
+#: forum/forms.py:27
+msgid "title must be > 10 characters"
+msgstr ""
+
+#: forum/forms.py:36
+msgid "content"
+msgstr ""
+
+#: forum/forms.py:42
+msgid "question content must be > 10 characters"
+msgstr ""
+
+#: forum/forms.py:52 forum/skins/default/templates/header.html:31
+#: forum/skins/default/templates/header.html:56
+msgid "tags"
+msgstr ""
+
+#: forum/forms.py:54
+msgid ""
+"Tags are short keywords, with no spaces within. Up to five tags can be used."
+msgstr ""
+
+#: forum/forms.py:61 forum/skins/default/templates/question_retag.html:43
+msgid "tags are required"
+msgstr ""
+
+#: forum/forms.py:67
+msgid "please use 5 tags or less"
+msgstr ""
+
+#: forum/forms.py:72
+msgid "tags must be shorter than 20 characters"
+msgstr ""
+
+#: forum/forms.py:74
+msgid ""
+"please use following characters in tags: letters 'a-z', numbers, and "
+"characters '.-_#'"
+msgstr ""
+
+#: forum/forms.py:84
+#: forum/skins/default/templates/post_contributor_info.html:7
+#: forum/skins/default/templates/question_summary_list_roll.html:26
+#: forum/skins/default/templates/question_summary_list_roll.html:38
+msgid "community wiki"
+msgstr ""
+
+#: forum/forms.py:85
+msgid ""
+"if you choose community wiki option, the question and answer do not generate "
+"points and name of author will not be shown"
+msgstr ""
+
+#: forum/forms.py:101
+msgid "update summary:"
+msgstr ""
+
+#: forum/forms.py:102
+msgid ""
+"enter a brief summary of your revision (e.g. fixed spelling, grammar, "
+"improved style, this field is optional)"
+msgstr ""
+
+#: forum/forms.py:105
+msgid "Automatically accept user's contributions for the email updates"
+msgstr ""
+
+#: forum/forms.py:118
+msgid "Your name:"
+msgstr ""
+
+#: forum/forms.py:119
+msgid "Email (not shared with anyone):"
+msgstr ""
+
+#: forum/forms.py:120
+msgid "Your message:"
+msgstr ""
+
+#: forum/forms.py:202
+msgid "this email does not have to be linked to gravatar"
+msgstr ""
+
+#: forum/forms.py:204
+msgid "Screen name"
+msgstr ""
+
+#: forum/forms.py:205
+msgid "Real name"
+msgstr ""
+
+#: forum/forms.py:206
+msgid "Website"
+msgstr ""
+
+#: forum/forms.py:207
+msgid "Location"
+msgstr ""
+
+#: forum/forms.py:208
+msgid "Date of birth"
+msgstr ""
+
+#: forum/forms.py:208
+msgid "will not be shown, used to calculate age, format: YYYY-MM-DD"
+msgstr ""
+
+#: forum/forms.py:209 forum/skins/default/templates/account_settings.html:21
+msgid "Profile"
+msgstr ""
+
+#: forum/forms.py:240 forum/forms.py:241
+msgid "this email has already been registered, please use another one"
+msgstr ""
+
+#: forum/subscriptions.py:41
+#, python-format
+msgid "New question on %(app_name)s"
+msgstr ""
+
+#: forum/subscriptions.py:73
+#, python-format
+msgid "New answer to '%(question_title)s'"
+msgstr ""
+
+#: forum/subscriptions.py:112
+#, python-format
+msgid "New comment on %(question_title)s"
+msgstr ""
+
+#: forum/subscriptions.py:136
+#, python-format
+msgid "An answer to '%(question_title)s' was accepted"
+msgstr ""
+
+#: forum/subscriptions.py:156
+#, python-format
+msgid "%(username)s is a new member on %(app_name)s"
+msgstr ""
+
+#: forum/urls.py:44
+msgid "upfiles/"
+msgstr ""
+
+#: forum/urls.py:49
+msgid "about/"
+msgstr ""
+
+#: forum/urls.py:50
+msgid "faq/"
+msgstr ""
+
+#: forum/urls.py:51
+msgid "privacy/"
+msgstr ""
+
+#: forum/urls.py:52
+msgid "logout/"
+msgstr ""
+
+#: forum/urls.py:53 forum/urls.py:54
+msgid "answers/"
+msgstr ""
+
+#: forum/urls.py:53 forum/urls.py:58 forum/urls.py:98
+#: forum/skins/default/templates/users/info.html:44
+msgid "edit/"
+msgstr ""
+
+#: forum/urls.py:54 forum/urls.py:74
+msgid "revisions/"
+msgstr ""
+
+#: forum/urls.py:55 forum/urls.py:56 forum/urls.py:57 forum/urls.py:58
+#: forum/urls.py:59 forum/urls.py:60 forum/urls.py:61 forum/urls.py:74
+msgid "questions/"
+msgstr ""
+
+#: forum/urls.py:56 forum_modules/books/urls.py:8
+msgid "ask/"
+msgstr ""
+
+#: forum/urls.py:57
+msgid "unanswered/"
+msgstr ""
+
+#: forum/urls.py:59
+msgid "close/"
+msgstr ""
+
+#: forum/urls.py:60
+msgid "reopen/"
+msgstr ""
+
+#: forum/urls.py:61
+msgid "answer/"
+msgstr ""
+
+#: forum/urls.py:63
+msgid "vote/"
+msgstr ""
+
+#: forum/urls.py:64
+msgid "like_comment/"
+msgstr ""
+
+#: forum/urls.py:65
+msgid "comment/"
+msgstr ""
+
+#: forum/urls.py:66
+msgid "delete_comment/"
+msgstr ""
+
+#: forum/urls.py:67
+msgid "accept_answer/"
+msgstr ""
+
+#: forum/urls.py:68
+msgid "mark_favorite/"
+msgstr ""
+
+#: forum/urls.py:69
+msgid "flag/"
+msgstr ""
+
+#: forum/urls.py:70
+msgid "delete/"
+msgstr ""
+
+#: forum/urls.py:71
+msgid "subscribe/"
+msgstr ""
+
+#: forum/urls.py:72
+msgid "matching_tags/"
+msgstr ""
+
+#: forum/urls.py:75
+msgid "command/"
+msgstr ""
+
+#: forum/urls.py:78
+msgid "question/"
+msgstr ""
+
+#: forum/urls.py:79 forum/urls.py:80
+msgid "tags/"
+msgstr ""
+
+#: forum/urls.py:82 forum/urls.py:86
+msgid "mark-tag/"
+msgstr ""
+
+#: forum/urls.py:82
+msgid "interesting/"
+msgstr ""
+
+#: forum/urls.py:86
+msgid "ignored/"
+msgstr ""
+
+#: forum/urls.py:90
+msgid "unmark-tag/"
+msgstr ""
+
+#: forum/urls.py:96 forum/urls.py:98 forum/urls.py:100 forum/urls.py:101
+#: forum/urls.py:102 forum/urls.py:103 forum/urls.py:104 forum/urls.py:105
+#: forum/models/user.py:124
+msgid "users/"
+msgstr ""
+
+#: forum/urls.py:97
+msgid "moderate-user/"
+msgstr ""
+
+#: forum/urls.py:100
+msgid "subscriptions/"
+msgstr ""
+
+#: forum/urls.py:101
+msgid "favorites/"
+msgstr ""
+
+#: forum/urls.py:102
+msgid "reputation/"
+msgstr ""
+
+#: forum/urls.py:103
+msgid "votes/"
+msgstr ""
+
+#: forum/urls.py:104
+msgid "recent/"
+msgstr ""
+
+#: forum/urls.py:107 forum/urls.py:108
+msgid "badges/"
+msgstr ""
+
+#: forum/urls.py:109
+msgid "messages/"
+msgstr ""
+
+#: forum/urls.py:109
+msgid "markread/"
+msgstr ""
+
+#: forum/urls.py:111
+msgid "nimda/"
+msgstr ""
+
+#: forum/urls.py:113
+msgid "upload/"
+msgstr ""
+
+#: forum/urls.py:114
+msgid "search/"
+msgstr ""
+
+#: forum/urls.py:115
+msgid "feedback/"
+msgstr ""
+
+#: forum/urls.py:119 forum/urls.py:120 forum/urls.py:121 forum/urls.py:122
+#: forum/urls.py:123 forum/urls.py:124 forum/urls.py:125 forum/urls.py:126
+#: forum/urls.py:127 forum/urls.py:128 forum/urls.py:129 forum/urls.py:130
+#: forum_modules/localauth/urls.py:7
+msgid "account/"
+msgstr ""
+
+#: forum/urls.py:119 forum/urls.py:121 forum/urls.py:122
+msgid "signin/"
+msgstr ""
+
+#: forum/urls.py:120
+msgid "signout/"
+msgstr ""
+
+#: forum/urls.py:123
+msgid "done/"
+msgstr ""
+
+#: forum/urls.py:124 forum_modules/localauth/urls.py:7
+msgid "register/"
+msgstr ""
+
+#: forum/urls.py:125
+msgid "validate/"
+msgstr ""
+
+#: forum/urls.py:126 forum/urls.py:127
+msgid "tempsignin/"
+msgstr ""
+
+#: forum/urls.py:128
+msgid "authsettings/"
+msgstr ""
+
+#: forum/urls.py:129 forum/urls.py:130
+msgid "providers/"
+msgstr ""
+
+#: forum/urls.py:129
+msgid "remove/"
+msgstr ""
+
+#: forum/urls.py:130
+msgid "add/"
+msgstr ""
+
+#: forum/urls.py:133 forum/urls.py:134 forum/urls.py:135 forum/urls.py:136
+#: forum/urls.py:137 forum_modules/sximporter/urls.py:8
+msgid "admin/"
+msgstr ""
+
+#: forum/urls.py:134
+msgid "denormalize/"
+msgstr ""
+
+#: forum/urls.py:135
+msgid "go_bootstrap/"
+msgstr ""
+
+#: forum/urls.py:136
+msgid "go_defaults/"
+msgstr ""
+
+#: forum/authentication/forms.py:21
+msgid "Your account email"
+msgstr ""
+
+#: forum/authentication/forms.py:23
+msgid "You cannot leave this field blank"
+msgstr ""
+
+#: forum/authentication/forms.py:24 forum/utils/forms.py:107
+msgid "please enter a valid email address"
+msgstr ""
+
+#: forum/authentication/forms.py:32
+msgid "Sorry, but this email is not on our database."
+msgstr ""
+
+#: forum/authentication/forms.py:40
+msgid "okay, let's try!"
+msgstr ""
+
+#: forum/authentication/forms.py:41
+msgid "no OSQA community email please, thanks"
+msgstr ""
+
+#: forum/authentication/forms.py:44
+msgid "please choose one of the options above"
+msgstr ""
+
+#: forum/authentication/forms.py:51
+msgid "Current password"
+msgstr ""
+
+#: forum/authentication/forms.py:62
+msgid ""
+"Old password is incorrect.                     Please enter the correct "
+"password."
+msgstr ""
+
+#: forum/management/commands/send_email_alerts.py:56
+msgid "Daily digest"
+msgstr ""
+
+#: forum/middleware/anon_user.py:34
+#, python-format
+msgid "First time here? Check out the <a href=\"%s\">FAQ</a>!"
+msgstr ""
+
+#: forum/models/question.py:30
+msgid "[closed] "
+msgstr ""
+
+#: forum/models/question.py:33
+msgid "[deleted] "
+msgstr ""
+
+#: forum/models/repute.py:13 forum/skins/default/templates/badges.html:53
+msgid "gold"
+msgstr ""
+
+#: forum/models/repute.py:14 forum/skins/default/templates/badges.html:61
+msgid "silver"
+msgstr ""
+
+#: forum/models/repute.py:15 forum/skins/default/templates/badges.html:68
+msgid "bronze"
+msgstr ""
+
+#: forum/models/tag.py:28
+msgid "interesting"
+msgstr ""
+
+#: forum/models/tag.py:28
+msgid "ignored"
+msgstr ""
+
+#: forum/models/user.py:255
+#: forum/skins/default/templates/post_contributor_info.html:19
+msgid "asked"
+msgstr ""
+
+#: forum/models/user.py:257
+#: forum/skins/default/templates/post_contributor_info.html:22
+msgid "answered"
+msgstr ""
+
+#: forum/models/user.py:259
+msgid "marked an answer"
+msgstr ""
+
+#: forum/models/user.py:261
+msgid "edited a question"
+msgstr ""
+
+#: forum/models/user.py:263
+msgid "commented a question"
+msgstr ""
+
+#: forum/models/user.py:265
+msgid "commented an answer"
+msgstr ""
+
+#: forum/models/user.py:267
+msgid "edited an answer"
+msgstr ""
+
+#: forum/models/user.py:269
+msgid "received badge"
+msgstr ""
+
+#: forum/settings/__init__.py:20
+msgid "Badges config"
+msgstr ""
+
+#: forum/settings/__init__.py:20
+msgid "Configure badges on your OSQA site."
+msgstr ""
+
+#: forum/settings/basic.py:9
+msgid "Basic Settings"
+msgstr ""
+
+#: forum/settings/basic.py:9
+msgid "The basic settings for your application"
+msgstr ""
+
+#: forum/settings/basic.py:12
+msgid "Application logo"
+msgstr ""
+
+#: forum/settings/basic.py:13
+msgid "Your site main logo."
+msgstr ""
+
+#: forum/settings/basic.py:17
+msgid "Favicon"
+msgstr ""
+
+#: forum/settings/basic.py:18
+msgid "Your site favicon."
+msgstr ""
+
+#: forum/settings/basic.py:22
+msgid "Application title"
+msgstr ""
+
+#: forum/settings/basic.py:23
+msgid "The title of your application that will show in the browsers title bar"
+msgstr ""
+
+#: forum/settings/basic.py:26
+msgid "Application short name"
+msgstr ""
+
+#: forum/settings/basic.py:30
+msgid "Application keywords"
+msgstr ""
+
+#: forum/settings/basic.py:31
+msgid "The meta keywords that will be available through the HTML meta tags."
+msgstr ""
+
+#: forum/settings/basic.py:34
+msgid "Application description"
+msgstr ""
+
+#: forum/settings/basic.py:35
+msgid "The description of your application"
+msgstr ""
+
+#: forum/settings/basic.py:39
+msgid "Application intro"
+msgstr ""
+
+#: forum/settings/basic.py:40
+msgid ""
+"The introductory page that is visible in the sidebar for anonymous users."
+msgstr ""
+
+#: forum/settings/basic.py:44
+msgid "Copyright notice"
+msgstr ""
+
+#: forum/settings/basic.py:45
+msgid "The copyright notice visible at the footer of your page."
+msgstr ""
+
+#: forum/settings/basic.py:48
+msgid "Maximum length of comment"
+msgstr ""
+
+#: forum/settings/basic.py:49
+msgid "The maximum length a user can enter for a comment."
+msgstr ""
+
+#: forum/settings/email.py:5
+msgid "Email Settings"
+msgstr ""
+
+#: forum/settings/email.py:5
+msgid "Email server and other email related settings."
+msgstr ""
+
+#: forum/settings/email.py:8
+msgid "Email Server"
+msgstr ""
+
+#: forum/settings/email.py:9
+msgid "The SMTP server through which your application will be sending emails."
+msgstr ""
+
+#: forum/settings/email.py:13
+msgid "Email Port"
+msgstr ""
+
+#: forum/settings/email.py:14
+msgid ""
+"The port on which your SMTP server is listening to. Usually this is 25, but "
+"can be something else."
+msgstr ""
+
+#: forum/settings/email.py:18
+msgid "Email User"
+msgstr ""
+
+#: forum/settings/email.py:19
+msgid "The username for your SMTP connection."
+msgstr ""
+
+#: forum/settings/email.py:23
+msgid "Email Password"
+msgstr ""
+
+#: forum/settings/email.py:24
+msgid "The password for your SMTP connection."
+msgstr ""
+
+#: forum/settings/email.py:29
+msgid "Use TLS"
+msgstr ""
+
+#: forum/settings/email.py:30
+msgid "Does your SMTP server usFes TLS for authentication."
+msgstr ""
+
+#: forum/settings/email.py:34
+msgid "Site 'from' email address"
+msgstr ""
+
+#: forum/settings/email.py:35
+msgid ""
+"The address that will show up on the 'from' field on emails sent by your "
+"website."
+msgstr ""
+
+#: forum/settings/email.py:39
+msgid "Email subject prefix"
+msgstr ""
+
+#: forum/settings/email.py:40
+msgid ""
+"Every email sent through your website will have the subject prefixed by this "
+"string. It's usually a good idea to have such a prefix so your users can "
+"easilly set up a filter on their email clients."
+msgstr ""
+
+#: forum/settings/extkeys.py:4
+msgid "External Keys"
+msgstr ""
+
+#: forum/settings/extkeys.py:4
+msgid ""
+"Keys for various external providers that your application may optionally use."
+msgstr ""
+
+#: forum/settings/extkeys.py:7
+msgid "Google sitemap code"
+msgstr ""
+
+#: forum/settings/extkeys.py:8
+msgid ""
+"This is the code you get when you register your site at <a href='https://www."
+"google.com/webmasters/tools/'>Google webmaster central</a>."
+msgstr ""
+
+#: forum/settings/extkeys.py:12
+msgid "Google analytics key"
+msgstr ""
+
+#: forum/settings/extkeys.py:13
+msgid ""
+"Your Google analytics key. You can get one at the <a href='http://www.google."
+"com/analytics/'>Google analytics official website</a>"
+msgstr ""
+
+#: forum/settings/forms.py:40
+msgid "Change this:"
+msgstr ""
+
+#: forum/settings/minrep.py:4
+msgid "Minimum reputation config"
+msgstr ""
+
+#: forum/settings/minrep.py:4
+msgid ""
+"Configure the minimum reputation required to perform certain actions on your "
+"site."
+msgstr ""
+
+#: forum/settings/minrep.py:7
+msgid "Minimum reputation to vote up"
+msgstr ""
+
+#: forum/settings/minrep.py:8
+msgid "The minimum reputation an user must have to be allowed to vote up."
+msgstr ""
+
+#: forum/settings/minrep.py:11
+msgid "Minimum reputation to vote down"
+msgstr ""
+
+#: forum/settings/minrep.py:12
+msgid "The minimum reputation an user must have to be allowed to vote down."
+msgstr ""
+
+#: forum/settings/minrep.py:15
+msgid "Minimum reputation to flag a post"
+msgstr ""
+
+#: forum/settings/minrep.py:16
+msgid "The minimum reputation an user must have to be allowed to flag a post."
+msgstr ""
+
+#: forum/settings/minrep.py:19
+msgid "Minimum reputation to comment"
+msgstr ""
+
+#: forum/settings/minrep.py:20
+msgid ""
+"The minimum reputation an user must have to be allowed to comment a post."
+msgstr ""
+
+#: forum/settings/minrep.py:23
+msgid "Minimum reputation to like a comment"
+msgstr ""
+
+#: forum/settings/minrep.py:24
+msgid ""
+"The minimum reputation an user must have to be allowed to \"like\" a comment."
+msgstr ""
+
+#: forum/settings/minrep.py:27
+msgid "Minimum reputation to upload"
+msgstr ""
+
+#: forum/settings/minrep.py:28
+msgid ""
+"The minimum reputation an user must have to be allowed to upload a file."
+msgstr ""
+
+#: forum/settings/minrep.py:31
+msgid "Minimum reputation to close own question"
+msgstr ""
+
+#: forum/settings/minrep.py:32
+msgid ""
+"The minimum reputation an user must have to be allowed to close his own "
+"question."
+msgstr ""
+
+#: forum/settings/minrep.py:35
+msgid "Minimum reputation to reopen own question"
+msgstr ""
+
+#: forum/settings/minrep.py:36
+msgid ""
+"The minimum reputation an user must have to be allowed to reopen his own "
+"question."
+msgstr ""
+
+#: forum/settings/minrep.py:39
+msgid "Minimum reputation to retag others questions"
+msgstr ""
+
+#: forum/settings/minrep.py:40
+msgid ""
+"The minimum reputation an user must have to be allowed to retag others "
+"questions."
+msgstr ""
+
+#: forum/settings/minrep.py:43
+msgid "Minimum reputation to edit wiki posts"
+msgstr ""
+
+#: forum/settings/minrep.py:44
+msgid ""
+"The minimum reputation an user must have to be allowed to edit community "
+"wiki posts."
+msgstr ""
+
+#: forum/settings/minrep.py:47
+msgid "Minimum reputation to edit others posts"
+msgstr ""
+
+#: forum/settings/minrep.py:48
+msgid ""
+"The minimum reputation an user must have to be allowed to edit others posts."
+msgstr ""
+
+#: forum/settings/minrep.py:51
+msgid "Minimum reputation to close others posts"
+msgstr ""
+
+#: forum/settings/minrep.py:52
+msgid ""
+"The minimum reputation an user must have to be allowed to close others posts."
+msgstr ""
+
+#: forum/settings/minrep.py:55
+msgid "Minimum reputation to delete comments"
+msgstr ""
+
+#: forum/settings/minrep.py:56
+msgid ""
+"The minimum reputation an user must have to be allowed to delete comments."
+msgstr ""
+
+#: forum/settings/minrep.py:59
+msgid "Minimum reputation to view offensive flags"
+msgstr ""
+
+#: forum/settings/minrep.py:60
+msgid "The minimum reputation an user must have to view offensive flags."
+msgstr ""
+
+#: forum/settings/repgain.py:4
+msgid "Reputation gains and losses config"
+msgstr ""
+
+#: forum/settings/repgain.py:4
+msgid ""
+"Configure the reputation points a user may gain or lose upon certain actions."
+msgstr ""
+
+#: forum/settings/repgain.py:7
+msgid "Initial reputation"
+msgstr ""
+
+#: forum/settings/repgain.py:8
+msgid "The initial reputation an user gets when he first signs in."
+msgstr ""
+
+#: forum/settings/repgain.py:12
+msgid "Maximum reputation a user can gain in one day for being upvoted."
+msgstr ""
+
+#: forum/settings/repgain.py:15
+msgid "Rep gain by upvoted"
+msgstr ""
+
+#: forum/settings/repgain.py:16
+msgid "Reputation a user gains for having one of his posts up voted."
+msgstr ""
+
+#: forum/settings/repgain.py:19
+msgid "Rep lost bu upvote canceled"
+msgstr ""
+
+#: forum/settings/repgain.py:20
+msgid ""
+"Reputation a user loses for having one of the upvotes on his posts canceled."
+msgstr ""
+
+#: forum/settings/repgain.py:23
+msgid "Rep lost by downvoted"
+msgstr ""
+
+#: forum/settings/repgain.py:24
+msgid "Reputation a user loses for having one of his posts down voted."
+msgstr ""
+
+#: forum/settings/repgain.py:27
+msgid "Rep lost by downvoting"
+msgstr ""
+
+#: forum/settings/repgain.py:28
+msgid "Reputation a user loses for down voting a post."
+msgstr ""
+
+#: forum/settings/repgain.py:31
+msgid "Rep gain by downvote canceled"
+msgstr ""
+
+#: forum/settings/repgain.py:32
+msgid ""
+"Reputation a user gains for having one of the downvotes on his posts "
+"canceled."
+msgstr ""
+
+#: forum/settings/repgain.py:35
+msgid "Rep gain by canceling downvote"
+msgstr ""
+
+#: forum/settings/repgain.py:36
+msgid "Reputation a user gains for canceling a downvote."
+msgstr ""
+
+#: forum/settings/repgain.py:39
+msgid "Rep gain by accepted answer"
+msgstr ""
+
+#: forum/settings/repgain.py:40
+msgid "Reputation a user gains for having one of his answers accepted."
+msgstr ""
+
+#: forum/settings/repgain.py:43
+msgid "Rep lost by accepted canceled"
+msgstr ""
+
+#: forum/settings/repgain.py:44
+msgid ""
+"Reputation a user loses for having one of his accepted answers canceled."
+msgstr ""
+
+#: forum/settings/repgain.py:47
+msgid "Rep gain by accepting answer"
+msgstr ""
+
+#: forum/settings/repgain.py:48
+msgid ""
+"Reputation a user gains for accepting an answer to one of his questions."
+msgstr ""
+
+#: forum/settings/repgain.py:51
+msgid "Rep lost by canceling accepted"
+msgstr ""
+
+#: forum/settings/repgain.py:52
+msgid "Reputation a user loses by canceling an accepted answer."
+msgstr ""
+
+#: forum/settings/repgain.py:55
+msgid "Rep lost by post flagged"
+msgstr ""
+
+#: forum/settings/repgain.py:56
+msgid "Reputation a user loses by having one of his posts flagged."
+msgstr ""
+
+#: forum/settings/repgain.py:59
+msgid "Rep lost by post flagged and hidden"
+msgstr ""
+
+#: forum/settings/repgain.py:60
+msgid ""
+"Reputation a user loses by having the last revision of one of his posts "
+"flagged the enough number of times to hide the post."
+msgstr ""
+
+#: forum/settings/repgain.py:63
+msgid "Rep lost by post flagged and deleted"
+msgstr ""
+
+#: forum/settings/repgain.py:64
+msgid ""
+"Reputation a user loses by having the last revision of one of his posts "
+"flagged the enough number of times to delete the post."
+msgstr ""
+
+#: forum/settings/upload.py:5
+msgid "File upload settings"
+msgstr ""
+
+#: forum/settings/upload.py:5
+msgid "File uploads related settings."
+msgstr ""
+
+#: forum/settings/upload.py:8
+msgid "Uploaded files folder"
+msgstr ""
+
+#: forum/settings/upload.py:9
+msgid ""
+"The filesystem path where uploaded files will be stored. Please note that "
+"this folder must exist."
+msgstr ""
+
+#: forum/settings/upload.py:12
+msgid "Uploaded files alias"
+msgstr ""
+
+#: forum/settings/upload.py:13
+msgid ""
+"The url alias for uploaded files. Notice that if you change this setting, "
+"you'll need to restart your site."
+msgstr ""
+
+#: forum/settings/upload.py:16
+msgid "Max file size"
+msgstr ""
+
+#: forum/settings/upload.py:17
+msgid "The maximum allowed file size for uploads in mb."
+msgstr ""
+
+#: forum/settings/voting.py:4
+msgid "Voting rules"
+msgstr ""
+
+#: forum/settings/voting.py:4
+msgid "Configure the voting rules on your site."
+msgstr ""
+
+#: forum/settings/voting.py:7
+msgid "Maximum votes per day"
+msgstr ""
+
+#: forum/settings/voting.py:8
+msgid "The maximum number of votes an user can cast per day."
+msgstr ""
+
+#: forum/settings/voting.py:11
+msgid "Start warning about votes left"
+msgstr ""
+
+#: forum/settings/voting.py:12
+msgid "From how many votes left should an user start to be warned about it."
+msgstr ""
+
+#: forum/settings/voting.py:15
+msgid "Maximum flags per day"
+msgstr ""
+
+#: forum/settings/voting.py:16
+msgid "The maximum number of times an can flag a post per day."
+msgstr ""
+
+#: forum/settings/voting.py:19
+msgid "Flag count to hide post"
+msgstr ""
+
+#: forum/settings/voting.py:20
+msgid ""
+"How many times a post needs to be flagged to be hidden from the main page."
+msgstr ""
+
+#: forum/settings/voting.py:23
+msgid "Flag count to delete post"
+msgstr ""
+
+#: forum/settings/voting.py:24
+msgid "How many times a post needs to be flagged to be deleted."
+msgstr ""
+
+#: forum/settings/voting.py:27
+msgid "Days to cancel a vote"
+msgstr ""
+
+#: forum/settings/voting.py:28
+msgid "How many days an user can cancel a vote after he originaly casted it."
+msgstr ""
+
+#: forum/skins/default/templates/404.html:24
+msgid "Sorry, could not find the page you requested."
+msgstr ""
+
+#: forum/skins/default/templates/404.html:26
+msgid "This might have happened for the following reasons:"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:28
+msgid "this question or answer has been deleted;"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:29
+msgid "url has error - please check it;"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:30
+msgid ""
+"the page you tried to visit is protected or you don't have sufficient "
+"points, see"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:31
+msgid "if you believe this error 404 should not have occured, please"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:32
+msgid "report this problem"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:41
+#: forum/skins/default/templates/500.html:27
+msgid "back to previous page"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:42
+msgid "see all questions"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:43
+msgid "see all tags"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:22
+msgid "sorry, system error"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:24
+msgid "system error log is recorded, error will be fixed as soon as possible"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:25
+msgid "please report the error to the site administrators if you wish"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:28
+msgid "see latest questions"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:29
+msgid "see tags"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:12
+#: forum/skins/default/templates/book.html:105
+#: forum/skins/default/templates/question_summary_list_roll.html:14
+#: forum/skins/default/templates/question_list/item.html:10
+#: forum/views/commands.py:82
+msgid "votes"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:14
+msgid "this answer has been accepted to be correct"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:16
+#: forum/skins/default/templates/question_summary_list_roll.html:13
+#: forum/skins/default/templates/question_list/item.html:14
+msgid "answers"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:20
+#: forum/skins/default/templates/book.html:115
+#: forum/skins/default/templates/question_summary_list_roll.html:15
+#: forum/skins/default/templates/question_list/item.html:18
+msgid "views"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:34
+#: forum/skins/default/templates/question.html:234
+#: forum/skins/default/templates/question_summary_list_roll.html:52
+#: forum/skins/default/templates/tags.html:49
+#: forum/skins/default/templates/question_list/item.html:29
+msgid "see questions tagged"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:34
+#: forum/skins/default/templates/book.html:125
+#: forum/skins/default/templates/question.html:234
+#: forum/skins/default/templates/question_summary_list_roll.html:52
+#: forum/skins/default/templates/tags.html:49
+#: forum/skins/default/templates/question_list/item.html:29
+msgid "using tags"
+msgstr ""
+
+#: forum/skins/default/templates/about.html:5
+#: forum/skins/default/templates/about.html:9
+msgid "About"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:4
+msgid "Account functions"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:29
+#: forum/skins/default/templates/auth/auth_settings.html:31
+msgid "Change password"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:30
+msgid "Give your  account a new password."
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:32
+msgid "Change email "
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:33
+msgid "Add or update the email address associated with your account."
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:35
+msgid "Change OpenID"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:36
+msgid "Change openid associated to your account"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:39
+msgid "Delete account"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:40
+msgid "Erase your username and all your data from website"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:5
+#: forum/skins/default/templates/answer_edit.html:39
+msgid "Edit answer"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:18
+#: forum/skins/default/templates/answer_edit.html:21
+#: forum/skins/default/templates/ask.html:19
+#: forum/skins/default/templates/ask.html:22
+#: forum/skins/default/templates/question_edit.html:19
+#: forum/skins/default/templates/question_edit.html:22
+msgid "hide preview"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:21
+#: forum/skins/default/templates/ask.html:22
+#: forum/skins/default/templates/question_edit.html:22
+msgid "show preview"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:39
+#: forum/skins/default/templates/question_edit.html:63
+#: forum/skins/default/templates/question_retag.html:56
+#: forum/skins/default/templates/revisions_answer.html:36
+#: forum/skins/default/templates/revisions_question.html:35
+msgid "back"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:44
+#: forum/skins/default/templates/question_edit.html:68
+#: forum/skins/default/templates/revisions_answer.html:50
+#: forum/skins/default/templates/revisions_question.html:49
+msgid "revision"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:47
+#: forum/skins/default/templates/question_edit.html:72
+msgid "select revision"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:54
+#: forum/skins/default/templates/ask.html:93
+#: forum/skins/default/templates/question.html:184
+#: forum/skins/default/templates/question_edit.html:89
+msgid "Toggle the real time Markdown editor preview"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:54
+#: forum/skins/default/templates/ask.html:93
+#: forum/skins/default/templates/question.html:185
+#: forum/skins/default/templates/question_edit.html:89
+msgid "toggle preview"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:63
+#: forum/skins/default/templates/question_edit.html:115
+#: forum/skins/default/templates/question_retag.html:77
+msgid "Save edit"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:64
+#: forum/skins/default/templates/close.html:29
+#: forum/skins/default/templates/feedback.html:50
+#: forum/skins/default/templates/question_edit.html:116
+#: forum/skins/default/templates/question_retag.html:78
+#: forum/skins/default/templates/reopen.html:30
+#: forum/skins/default/templates/users/edit.html:87
+msgid "Cancel"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:4
+msgid "answer tips"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:7
+msgid "please make your answer relevant to this community"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:10
+msgid "try to give an answer, rather than engage into a discussion"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:13
+msgid "please try to provide details"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:16
+#: forum/skins/default/templates/question_edit_tips.html:18
+msgid "be clear and concise"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:20
+#: forum/skins/default/templates/question_edit_tips.html:22
+msgid "see frequently asked questions"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:26
+#: forum/skins/default/templates/question_edit_tips.html:28
+msgid "Markdown tips"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:29
+#: forum/skins/default/templates/question_edit_tips.html:31
+msgid "*italic* or __italic__"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:32
+#: forum/skins/default/templates/question_edit_tips.html:34
+msgid "**bold** or __bold__"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:35
+#: forum/skins/default/templates/question_edit_tips.html:37
+msgid "link"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:35
+#: forum/skins/default/templates/answer_edit_tips.html:39
+#: forum/skins/default/templates/question_edit_tips.html:37
+#: forum/skins/default/templates/question_edit_tips.html:42
+msgid "text"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:39
+#: forum/skins/default/templates/question_edit_tips.html:42
+msgid "image"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:43
+#: forum/skins/default/templates/question_edit_tips.html:46
+msgid "numbered list:"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:48
+#: forum/skins/default/templates/question_edit_tips.html:51
+msgid "basic HTML tags are also supported"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:52
+#: forum/skins/default/templates/question_edit_tips.html:55
+msgid "learn more about Markdown"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:5
+#: forum/skins/default/templates/ask.html:57
+msgid "Ask a question"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:64
+msgid "login to post question info"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:70
+#, python-format
+msgid ""
+"must have valid %(email)s to post, \n"
+"                            see %(email_validation_faq_url)s\n"
+"                            "
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:108
+msgid "(required)"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:115
+msgid "Login/signup to post your question"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:117
+msgid "Ask your question"
+msgstr ""
+
+#: forum/skins/default/templates/badge.html:6
+#: forum/skins/default/templates/badge.html:17
+msgid "Badge"
+msgstr ""
+
+#: forum/skins/default/templates/badge.html:26
+msgid "The users have been awarded with badges:"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:6
+msgid "Badges summary"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:17
+msgid "Badges"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:21
+msgid "Community gives you awards for your questions, answers and votes."
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:22
+#, python-format
+msgid ""
+"Below is the list of available badges and number \n"
+"    of times each type of badge has been awarded. Give us feedback at %"
+"(feedback_faq_url)s.\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:50
+msgid "Community badges"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:56
+msgid "gold badge description"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:64
+msgid "silver badge description"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:67
+msgid "bronze badge: often given as a special honor"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:71
+msgid "bronze badge description"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:7
+msgid "reading channel"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:26
+msgid "[author]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:30
+msgid "[publisher]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:34
+msgid "[publication date]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:38
+msgid "[price]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:39
+msgid "currency unit"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:42
+msgid "[pages]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:43
+msgid "pages abbreviation"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:46
+msgid "[tags]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:56
+msgid "author blog"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:62
+msgid "book directory"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:66
+msgid "buy online"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:79
+msgid "reader questions"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:82
+msgid "ask the author"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:88
+#: forum/skins/default/templates/book.html:93
+msgid "this question was selected as favorite"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:88
+#: forum/skins/default/templates/book.html:93
+msgid "number of times"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:108
+msgid "the answer has been accepted to be correct"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:147
+msgid "subscribe to book RSS feed"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:147
+msgid "subscribe to the questions feed"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:6
+#: forum/skins/default/templates/close.html:16
+msgid "Close question"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:19
+msgid "Close the question"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:25
+msgid "Reasons"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:28
+msgid "OK to close"
+msgstr ""
+
+#: forum/skins/default/templates/email_base.html:31
+msgid "home"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:11
+msgid "Frequently Asked Questions "
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:16
+msgid "What kinds of questions can I ask here?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:17
+msgid ""
+"Most importantly - questions should be <strong>relevant</strong> to this "
+"community."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:18
+msgid ""
+"Before asking the question - please make sure to use search to see whether "
+"your question has alredy been answered."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:21
+msgid "What questions should I avoid asking?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:22
+msgid ""
+"Please avoid asking questions that are not relevant to this community, too "
+"subjective and argumentative."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:27
+msgid "What should I avoid in my answers?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:28
+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 ""
+
+#: forum/skins/default/templates/faq.html:32
+msgid "Who moderates this community?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:33
+msgid "The short answer is: <strong>you</strong>."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:34
+msgid "This website is moderated by the users."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:35
+msgid ""
+"The reputation system allows users earn the authorization to perform a "
+"variety of moderation tasks."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:40
+msgid "How does reputation system work?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:41
+msgid "Rep system summary"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:42
+msgid ""
+"For example, if you ask an interesting question or give a helpful answer, "
+"your input will be upvoted. On the other hand if the answer is misleading - "
+"it will be downvoted. Each vote in favor will generate <strong>10</strong> "
+"points, each vote against will subtract <strong>2</strong> points. There is "
+"a limit of <strong>200</strong> points that can be accumulated per question "
+"or answer. The table below explains reputation point requirements for each "
+"type of moderation task."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:53
+#: forum/skins/default/templates/users/votes.html:15
+#: forum/views/commands.py:77
+msgid "upvote"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:57
+msgid "use tags"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:62
+msgid "add comments"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:66
+#: forum/skins/default/templates/users/votes.html:17
+#: forum/views/commands.py:77
+msgid "downvote"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:69
+msgid "open and close own questions"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:73
+msgid "retag questions"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:78
+msgid "edit community wiki questions"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:83
+msgid "edit any answer"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:87
+msgid "open any closed question"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:91
+msgid "delete any comment"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:95
+msgid "delete any questions and answers and perform other moderation tasks"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:103
+msgid "how to validate email title"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:105
+#, python-format
+msgid ""
+"how to validate email info with %(send_email_key_url)s %(gravatar_faq_url)s"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:110
+msgid "what is gravatar"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:111
+msgid "gravatar faq info"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:114
+msgid "To register, do I need to create new password?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:115
+msgid ""
+"No, you don't have to. You can login through any service that supports "
+"OpenID, e.g. Google, Yahoo, AOL, etc."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:116
+msgid "Login now!"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:121
+msgid "Why other people can edit my questions/answers?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:122
+msgid "Goal of this site is..."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:122
+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 ""
+
+#: forum/skins/default/templates/faq.html:123
+msgid "If this approach is not for you, we respect your choice."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:127
+msgid "Still have questions?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:128
+#, python-format
+msgid ""
+"Please ask your question at %(ask_question_url)s, help make our community "
+"better!"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:130
+#: forum/skins/default/templates/header.html:30
+#: forum/skins/default/templates/header.html:55 forum/views/readers.py:76
+msgid "questions"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:130
+msgid "."
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:6
+msgid "Feedback"
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:11
+msgid "Give us your feedback!"
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:17
+#, python-format
+msgid ""
+"\n"
+"            <span class='big strong'>Dear %(user_name)s</span>, we look "
+"forward to hearing your feedback. \n"
+"            Please type and send us your message below.\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:24
+msgid ""
+"\n"
+"            <span class='big strong'>Dear visitor</span>, we look forward to "
+"hearing your feedback.\n"
+"            Please type and send us your message below.\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:41
+msgid "(this field is required)"
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:49
+msgid "Send Feedback"
+msgstr ""
+
+#: forum/skins/default/templates/footer.html:7
+#: forum/skins/default/templates/header.html:16
+#: forum/skins/default/templates/index.html:12
+msgid "about"
+msgstr ""
+
+#: forum/skins/default/templates/footer.html:8
+#: forum/skins/default/templates/header.html:17
+#: forum/skins/default/templates/index.html:13
+#: forum/skins/default/templates/question_edit_tips.html:22
+msgid "faq"
+msgstr ""
+
+#: forum/skins/default/templates/footer.html:9
+msgid "privacy policy"
+msgstr ""
+
+#: forum/skins/default/templates/footer.html:18
+msgid "give feedback"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:9
+msgid "administration"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:12
+msgid "logout"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:14
+msgid "login"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:24
+msgid "back to home page"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:32
+#: forum/skins/default/templates/header.html:57
+msgid "users"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:33
+#: forum/skins/default/templates/users/signature.html:9
+#: forum/skins/default/templates/users/signature.html:15
+#: forum/skins/default/templates/users/signature.html:21
+#: forum/templatetags/extra_tags.py:167 forum/templatetags/extra_tags.py:196
+msgid "badges"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:34
+msgid "unanswered questions"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:36
+msgid "ask a question"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:51
+msgid "search"
+msgstr ""
+
+#: forum/skins/default/templates/index.html:9
+msgid "welcome to "
+msgstr ""
+
+#: forum/skins/default/templates/logout.html:6
+#: forum/skins/default/templates/logout.html:16
+msgid "Logout"
+msgstr ""
+
+#: forum/skins/default/templates/logout.html:19
+msgid ""
+"As a registered user you can login with your OpenID, log out of the site or "
+"permanently remove your account."
+msgstr ""
+
+#: forum/skins/default/templates/logout.html:20
+msgid "Logout now"
+msgstr ""
+
+#: forum/skins/default/templates/notarobot.html:3
+msgid "Please prove that you are a Human Being"
+msgstr ""
+
+#: forum/skins/default/templates/notarobot.html:10
+msgid "I am a Human Being"
+msgstr ""
+
+#: forum/skins/default/templates/pagesize.html:6
+msgid "posts per page"
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:6
+#: forum/skins/default/templates/paginator.html:7
+msgid "previous"
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:19
+msgid "current page"
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:22
+#: forum/skins/default/templates/paginator.html:29
+msgid "page number "
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:22
+#: forum/skins/default/templates/paginator.html:29
+msgid "number - make blank in english"
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:33
+msgid "next page"
+msgstr ""
+
+#: forum/skins/default/templates/post_contributor_info.html:9
+#, python-format
+msgid ""
+"\n"
+"                one revision\n"
+"            "
+msgid_plural ""
+"\n"
+"                %(rev_count)s revisions\n"
+"            "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/post_contributor_info.html:24
+msgid "posted"
+msgstr ""
+
+#: forum/skins/default/templates/post_contributor_info.html:45
+msgid "updated"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:6
+#: forum/skins/default/templates/privacy.html:11
+msgid "Privacy policy"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:15
+msgid "general message about privacy"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:18
+msgid "Site Visitors"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:20
+msgid "what technical information is collected about visitors"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:23
+msgid "Personal Information"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:25
+msgid "details on personal information policies"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:28
+msgid "Other Services"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:30
+msgid "details on sharing data with third parties"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:35
+msgid "cookie policy details"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:37
+msgid "Policy Changes"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:38
+msgid "how privacy policies can be changed"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:70
+#: forum/skins/default/templates/sidebar/recent_tags.html:9
+#, python-format
+msgid "see questions tagged '%(tagname)s'"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:87
+#, python-format
+msgid ""
+"The question has been closed for the following reason \"%(close_reason)s\" by"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:89
+#, python-format
+msgid "close date %(closed_at)s"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:97
+#, python-format
+msgid ""
+"\n"
+"                    One Answer:\n"
+"                    "
+msgid_plural ""
+"\n"
+"                    %(counter)s Answers:\n"
+"                    "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/question.html:105
+msgid "oldest answers will be shown first"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:105
+msgid "oldest answers"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:107
+msgid "newest answers will be shown first"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:107
+msgid "newest answers"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:109
+msgid "most voted answers will be shown first"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:109
+msgid "popular answers"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:157
+msgid "Your answer"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:159
+msgid "Be the first one to answer this question!"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:165
+msgid "you can answer anonymously and then login"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:169
+msgid "answer your own question only to give an answer"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:171
+msgid "please only give an answer, no discussions"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:207
+msgid "Login/Signup to Post Your Answer"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:210
+msgid "Answer Your Own Question"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:212
+msgid "Answer the question"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:229
+msgid "Question tags"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:239
+msgid "question asked"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:242
+msgid "question was seen"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:242
+msgid "times"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:245
+msgid "last updated"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:250
+msgid "Related questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_edit.html:5
+#: forum/skins/default/templates/question_edit.html:63
+msgid "Edit question"
+msgstr ""
+
+#: forum/skins/default/templates/question_edit_tips.html:4
+msgid "question tips"
+msgstr ""
+
+#: forum/skins/default/templates/question_edit_tips.html:9
+#, python-format
+msgid ""
+"\n"
+"                ask a question relevant to the %(app_title)s community \n"
+"                "
+msgstr ""
+
+#: forum/skins/default/templates/question_edit_tips.html:15
+msgid "please try provide enough details"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:5
+#: forum/skins/default/templates/question_retag.html:56
+msgid "Change tags"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:44
+msgid "up to 5 tags, less than 20 characters each"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:86
+msgid "Why use and modify tags?"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:89
+msgid "tags help us keep Questions organized"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:97
+msgid "tag editors receive special awards from the community"
+msgstr ""
+
+#: forum/skins/default/templates/questions.html:7
+msgid "Questions"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:6
+#: forum/skins/default/templates/reopen.html:16
+msgid "Reopen question"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:19
+msgid "Open the previously closed question"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:22
+msgid "The question was closed for the following reason "
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:22
+msgid "reason - leave blank in english"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:22
+msgid "on "
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:22
+msgid "date closed"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:29
+msgid "Reopen this question"
+msgstr ""
+
+#: forum/skins/default/templates/revisions_answer.html:7
+#: forum/skins/default/templates/revisions_answer.html:36
+#: forum/skins/default/templates/revisions_question.html:7
+#: forum/skins/default/templates/revisions_question.html:35
+msgid "Revision history"
+msgstr ""
+
+#: forum/skins/default/templates/revisions_answer.html:48
+#: forum/skins/default/templates/revisions_question.html:47
+msgid "click to hide/show revision"
+msgstr ""
+
+#: forum/skins/default/templates/revisions_answer.html:56
+#: forum/templatetags/node_tags.py:62
+msgid "edit"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:3
+msgid "Subscription"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:8
+msgid "You were automatically subscribed to this question."
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:10
+msgid "You are subscribed to this question."
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:13
+msgid "You are not subscribed to this question."
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:18
+#: forum/views/commands.py:323
+msgid "unsubscribe me"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:20
+#: forum/views/commands.py:323
+msgid "subscribe me"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:24
+#, python-format
+msgid ""
+"\n"
+"            (you can adjust your notification settings on your <a href=\"%"
+"(profile_url)s?sort=email_subscriptions\">profile</a>)\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:29
+msgid "Once you sign in you will be able to subscribe for any updates here"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:4
+#: forum/skins/default/templates/question_list/tag_selector.html:6
+msgid "Interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:10
+#: forum/skins/default/templates/tag_selector.html:27
+#: forum/skins/default/templates/question_list/related_tags.html:9
+#: forum/skins/default/templates/question_list/tag_selector.html:12
+#: forum/skins/default/templates/question_list/tag_selector.html:29
+#, python-format
+msgid "see questions tagged '%(tag_name)s'"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:14
+#: forum/skins/default/templates/question_list/tag_selector.html:16
+#, python-format
+msgid "remove '%(tag_name)s' from the list of interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:20
+#: forum/skins/default/templates/tag_selector.html:37
+#: forum/skins/default/templates/question_list/tag_selector.html:22
+#: forum/skins/default/templates/question_list/tag_selector.html:39
+msgid "Add"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:21
+#: forum/skins/default/templates/question_list/tag_selector.html:23
+msgid "Ignored tags"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:31
+#: forum/skins/default/templates/question_list/tag_selector.html:33
+#, python-format
+msgid "remove '%(tag_name)s' from the list of ignored tags"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:40
+#: forum/skins/default/templates/question_list/tag_selector.html:42
+msgid "keep ignored questions hidden"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:6
+#: forum/skins/default/templates/tags.html:30
+msgid "Tag list"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:32
+msgid "sorted alphabetically"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:32
+msgid "by name"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:33
+msgid "sorted by frequency of tag use"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:33
+msgid "by popularity"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:39
+msgid "All tags matching query"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:39
+msgid "all tags - make this empty in english"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:42
+msgid "Nothing found"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:5
+#: forum/skins/default/templates/auth/auth_settings.html:7
+msgid "Authentication settings"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:9
+msgid ""
+"These are the external authentication providers currently associated with "
+"your account."
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:12
+msgid "remove"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:17
+msgid ""
+"You currently have no external authentication provider associated with your "
+"account."
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:19
+msgid "Add new provider"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:21
+msgid "This is where you can change your password. Make sure you remember it!"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:24
+msgid ""
+"You can set up a password for your account, so you can login using standard "
+"username and password!"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:31
+msgid "Create password"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:5
+msgid "Connect your OpenID with this site"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:8
+msgid "Connect your OpenID with your account on this site"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:12
+msgid "You are here for the first time with "
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:13
+msgid ""
+"Please create your screen name and save your email address. Saved email "
+"address will let you subscribe for the updates on the most interesting "
+"questions and will be used to create and retrieve your unique avatar image. "
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:15
+msgid "This account already exists, please use another."
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:30
+msgid "Sorry, looks like we have some errors:"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:47
+msgid "Screen name label"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:54
+msgid "Email address label"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:60
+#: forum/skins/default/templates/auth/signup.html:18
+msgid "receive updates motivational blurb"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:64
+#: forum/skins/default/templates/auth/signup.html:22
+msgid "please select one of the options above"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:67
+msgid "Tag filter tool will be your right panel, once you log in."
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:68
+msgid "create account"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:77
+msgid "Existing account"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:78
+msgid "user name"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:79
+msgid "password"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:86
+msgid "Register"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:87
+msgid "Forgot your password?"
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:6
+#: forum/skins/default/templates/auth/temp_login_email.html:6
+msgid "Greetings from the Q&A forum"
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:8
+msgid "To make use of the Forum, please follow the link below:"
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:12
+msgid "Following the link above will help us verify your email address."
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:14
+#: forum/skins/default/templates/auth/temp_login_email.html:14
+msgid ""
+"If you beleive that this message was sent in mistake -\n"
+"    no further action is needed. Just ingore this email, we apologize\n"
+"    for any inconvenience"
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:18
+#: forum/skins/default/templates/auth/temp_login_email.html:18
+#: forum/skins/default/templates/notifications/answeraccepted.html:15
+#: forum/skins/default/templates/notifications/newanswer.html:25
+#: forum/skins/default/templates/notifications/newcomment.html:32
+#: forum/skins/default/templates/notifications/newmember.html:15
+#: forum/skins/default/templates/notifications/newquestion.html:25
+msgid ""
+"Sincerely,<br />\n"
+"    Forum Administrator"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:6
+msgid "Login"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:24
+msgid "User login"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:36
+#: forum/skins/default/templates/auth/signin.html:86
+#: forum/skins/default/templates/auth/signin.html:92
+msgid "Or..."
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:39
+msgid "Click to sign in through any of these services."
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:44
+msgid "Validate my email after I login."
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:94
+msgid "Click"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:94
+msgid "if you're having trouble signing in."
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:98
+msgid "Enter your "
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:154
+msgid "Why use OpenID?"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:157
+msgid "with openid it is easier"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:160
+msgid "reuse openid"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:163
+msgid "openid is widely adopted"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:166
+msgid "openid is supported open standard"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:171
+msgid "Find out more"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:172
+msgid "Get OpenID"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:4
+msgid "Signup"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:8
+msgid "Create login name and password"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:10
+msgid "Traditional signup info"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:31
+msgid "Create Account"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:32
+msgid "or"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:33
+msgid "return to login page"
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_email.html:8
+msgid "You're seeing this because someone requested a temporary login link"
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_email.html:12
+msgid "Following the link above will give you access to your account."
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:5
+msgid "Request temporary login key"
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:7
+msgid "Account: request temporary login key"
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:8
+msgid ""
+"\n"
+"    If you're experiencing problems accessing your account, or if you forgot "
+"your password,\n"
+"    here you can request a temporary login key. Fill out your account email "
+"and we'll send you a temporary access link that\n"
+"    will enable you to access your account. This token is valid only once "
+"and for a limited period of time.\n"
+" "
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:25
+msgid "Send link"
+msgstr ""
+
+#: forum/skins/default/templates/node/accept_button.html:5
+#, python-format
+msgid "%(who)s has selected this answer as the correct answer"
+msgstr ""
+
+#: forum/skins/default/templates/node/accept_button.html:5
+msgid "mark this answer as the accepted answer"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:22
+msgid "I like this comment (click again to cancel)"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:26
+msgid "Edit comment"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:30
+msgid "Delete comment"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:42
+#, python-format
+msgid "showing %(showing)s of %(total)s"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:44
+msgid "show all"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:47
+msgid "add new comment"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:55
+msgid " add comment"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:58
+#, python-format
+msgid ""
+"\n"
+"                have <span class=\"comments-char-left-count\">%(max_length)"
+"s</span> characters left\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:71
+msgid "just now"
+msgstr ""
+
+#: forum/skins/default/templates/node/favorite_mark.html:3
+msgid "mark/unmark this question as favorite (click again to cancel)"
+msgstr ""
+
+#: forum/skins/default/templates/node/vote_buttons.html:3
+msgid "I like this post (click again to cancel)"
+msgstr ""
+
+#: forum/skins/default/templates/node/vote_buttons.html:7
+msgid "current number of votes"
+msgstr ""
+
+#: forum/skins/default/templates/node/vote_buttons.html:10
+msgid "I dont like this post (click again to cancel)"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/answeraccepted.html:6
+#: forum/skins/default/templates/notifications/digest.html:7
+#: forum/skins/default/templates/notifications/newanswer.html:6
+#: forum/skins/default/templates/notifications/newcomment.html:6
+#: forum/skins/default/templates/notifications/newmember.html:6
+#: forum/skins/default/templates/notifications/newquestion.html:6
+msgid "Hello"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/answeraccepted.html:9
+#, python-format
+msgid ""
+"\n"
+"        Just to let you know that %(accepter)s has just accepted %"
+"(answer_author)s's answer on his question\n"
+"        <a href=\"%(app_url)s%(question_url)s\">%(question_title)s</a>:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:9
+#, python-format
+msgid ""
+"\n"
+"    This is the %(digest_type)s activity digest for %(app_title)s\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:15
+#, python-format
+msgid ""
+"\n"
+"            %(nusers_count)s new user%(nusers_count_pluralize)s joined the %"
+"(app_title)s community:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:28
+#, python-format
+msgid ""
+"\n"
+"            %(question_count)s of your subscriptions have updates:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:35
+msgid "On question "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:37
+#, python-format
+msgid ""
+"\n"
+"                    %(answer_count)s new answer%(answer_count_pluralize)s\n"
+"                "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:42
+#, python-format
+msgid ""
+"\n"
+"                    %(comment_count)s new comment%(comment_count_pluralize)"
+"s\n"
+"                "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:46
+msgid "on your own post(s)"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:50
+msgid "an answer was accepted"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:59
+#, python-format
+msgid ""
+"\n"
+"            %(question_count)s new question%(question_count_pluralize)s\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:63
+msgid "matching your interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:65
+msgid "posted :"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:71
+#, python-format
+msgid ""
+"\n"
+"                    Posted by %(author_name)s in %(question_time)s\n"
+"                "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:7
+#, python-format
+msgid ""
+"\n"
+"    Hello, this is a %(site_title)s forum feedback message\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:13
+msgid "Sender"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:15
+#: forum/skins/default/templates/notifications/feedback.html:18
+#: forum/skins/default/templates/users/info.html:93
+msgid "email"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:17
+msgid "anonymous"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:25
+msgid "Message body:"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newanswer.html:9
+#, python-format
+msgid ""
+"\n"
+"        %(author_name)s has just posted a new answer on %(app_title)s to the "
+"question\n"
+"        <a href=\"%(app_url)s%(question_url)s\">%(question_title)s\"</a>:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newanswer.html:20
+#: forum/skins/default/templates/notifications/newcomment.html:28
+#: forum/skins/default/templates/notifications/newquestion.html:20
+msgid ""
+"\n"
+"        Don't forget to come over and cast your vote.\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newcomment.html:9
+#, python-format
+msgid ""
+"\n"
+"            %(author_name)s has just posted a comment on\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newcomment.html:14
+#, python-format
+msgid ""
+"\n"
+"                the answer posted by <a href=\"%(app_url)s%(poster_url)s\">%"
+"(poster_name)s</a> to\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newcomment.html:19
+#, python-format
+msgid ""
+"\n"
+"             the question  <a href=\"%(app_url)s%(question_url)s\">%"
+"(question_title)s</a>\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newmember.html:9
+#, python-format
+msgid ""
+"\n"
+"        %(newmember_name)s has just joined %(app_title)s. You can visit %"
+"(newmember_name)s's profile using the following link: <br />\n"
+"        <a href=\"%(app_url)s%(newmember_url)s\">%(newmember_name)s profile</"
+"a>\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newquestion.html:9
+#, python-format
+msgid ""
+"\n"
+"        %(author_name)s has just posted a new question on %(app_title)s, "
+"with title\n"
+"        <a href=\"%(app_url)s%(question_url)s\">%(question_title)s</a> and "
+"tagged <em>%(question_tags)s</em>:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/base.html:13
+msgid "OSQA administration area"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/base.html:26
+msgid "Administration menu"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:7
+msgid "Dashboard"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:10
+msgid "Welcome to the OSQA administration area."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:17
+msgid "Site statistics"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:21
+#: forum/skins/default/templates/osqaadmin/index.html:26
+msgid "in the last 24 hours"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:31
+msgid "user"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:31
+msgid "joined in the last 24 hours"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:37
+msgid "Site status"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:42
+msgid ""
+"Your site is running in bootstrap mode, click the button bellow to revert to "
+"defaults."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:45
+msgid ""
+"Your site is running in standard mode, click the button bellow to run in "
+"bootstrap mode."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:47
+msgid ""
+"Your site is running with some customized settings, click the buttons bellow "
+"to run with defaults or in bootstrap mode"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:51
+msgid "Are you sure you want to revert to the defaults?"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:51
+msgid "revert to defaults"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:54
+msgid "Are you sure you want to run bootstrap mode?"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:54
+msgid "go bootstrap"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:59
+msgid "Recalculate scores and reputation"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:60
+msgid "This is a heavy operation, are you sure?"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:60
+msgid "Recalculate"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:65
+msgid "Recent activity"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/item.html:12
+msgid "this question has an accepted answer"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/related_tags.html:6
+msgid "Related tags"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:4
+msgid "most recently updated questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:4
+msgid "active"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:5
+msgid "most recently asked questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:5
+msgid "newest"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:6
+msgid "hottest questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:6
+msgid "hottest"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:7
+msgid "most voted questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:7
+msgid "most voted"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:5
+msgid "Found by tags"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:9
+msgid "Search results"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:11
+msgid "Found by title"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:15
+msgid "Unanswered questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:17
+#: forum/skins/default/templates/users/subscriptions.html:74
+msgid "All questions"
+msgstr ""
+
+#: forum/skins/default/templates/sidebar/recent_awards.html:4
+msgid "Recent awards"
+msgstr ""
+
+#: forum/skins/default/templates/sidebar/recent_awards.html:15
+msgid "all awards"
+msgstr ""
+
+#: forum/skins/default/templates/sidebar/recent_tags.html:4
+msgid "Recent tags"
+msgstr ""
+
+#: forum/skins/default/templates/sidebar/recent_tags.html:12
+msgid "popular tags"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:6
+msgid "Edit user profile"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:19
+msgid "edit profile"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:31
+msgid "image associated with your email address"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:31
+#, python-format
+msgid "avatar, see %(gravatar_faq_url)s"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:36
+#: forum/skins/default/templates/users/info.html:52
+msgid "Registered user"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:43
+msgid "Screen Name"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:86
+#: forum/skins/default/templates/users/subscriptions.html:116
+msgid "Update"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:22
+#: forum/skins/default/templates/users/signature.html:6
+#: forum/skins/default/templates/users/users.html:26
+msgid "reputation"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:32
+msgid "Moderate this user"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:44
+msgid "update profile"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:56
+msgid "real name"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:61
+msgid "member for"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:66
+msgid "last seen"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:72
+msgid "user website"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:78
+msgid "location"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:86
+msgid "age"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:87
+msgid "age unit"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:100
+msgid "todays unused votes"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:101
+msgid "votes left"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:13
+#, python-format
+msgid ""
+"\n"
+"                <span class=\"count\">1</span> Question\n"
+"                "
+msgid_plural ""
+"\n"
+"                <span class=\"count\">%(counter)s</span> Questions\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:29
+#, python-format
+msgid ""
+"\n"
+"                <span class=\"count\">1</span> Answer\n"
+"                "
+msgid_plural ""
+"\n"
+"                <span class=\"count\">%(counter)s</span> Answers\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:42
+#, python-format
+msgid "the answer has been voted for %(vote_count)s times"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:42
+msgid "this answer has been selected as correct"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:58
+#, python-format
+msgid ""
+"\n"
+"                    <span class=\"count\">1</span> Vote\n"
+"                "
+msgid_plural ""
+"\n"
+"                    <span class=\"count\">%(cnt)s</span> Votes\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:69
+msgid "thumb up"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:70
+msgid "user has voted up this many times"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:74
+msgid "thumb down"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:75
+msgid "user voted down this many times"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:84
+#, python-format
+msgid ""
+"\n"
+"                    <span class=\"count\">1</span> Tag\n"
+"                "
+msgid_plural ""
+"\n"
+"                    <span class=\"count\">%(counter)s</span> Tags\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:97
+#, python-format
+msgid ""
+"see other questions with %(view_user)s's contributions tagged '%(tag_name)s' "
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:112
+#, python-format
+msgid ""
+"\n"
+"            <span class=\"count\">1</span> Badge\n"
+"            "
+msgid_plural ""
+"\n"
+"            <span class=\"count\">%(counter)s</span> Badges\n"
+"            "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/subscriptions.html:8
+msgid "Notifications and subscription settings"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:10
+msgid ""
+"\n"
+"        Here you can decide which types of notifications you wish to "
+"receive, and it's frequency.<br />\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:14
+msgid ""
+"\n"
+"        Currently you have notifications enabled. You can always stop all "
+"notifications without loosing your settings and restart them afterwards.<br /"
+">\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:18
+msgid ""
+"\n"
+"        Currently you have notifications disabled. You can enable them "
+"clicking on the <strong>Start notifications</strong> button bellow.<br />\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:28
+msgid "Notify me when:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:32
+msgid "A new member joins"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:36
+msgid "A new question is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:40
+msgid "A new question matching my interesting tags is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:44
+msgid "There's an update on one of my subscriptions"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:52
+msgid "Auto subscribe me to:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:57
+msgid "Questions I ask"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:60
+msgid "Questions I answer"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:63
+msgid "Questions I comment"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:68
+msgid "Questions I view"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:71
+msgid "All questions matching my interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:82
+msgid "On my subscriptions, notify me when:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:87
+msgid "An answer is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:90
+msgid "A comment on one of my posts is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:95
+msgid "A comment is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:98
+msgid "An answer is accepted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:106
+msgid "More:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:111
+msgid ""
+"Notify me when someone replys to one of my comments on any post using the "
+"<pre>@username</pre> notation"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:118
+msgid "Stop notifications"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:120
+msgid "Start notifications"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:7
+msgid "User profile"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:7
+msgid "overview"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:9
+msgid "recent activity"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:11
+msgid "graph of user reputation"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:12
+msgid "reputation history"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:15 forum/views/users.py:196
+msgid "user vote record"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:15
+msgid "casted votes"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:18
+msgid "questions that user selected as his/her favorite"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:19
+msgid "favorites"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:22
+msgid "email subscription settings"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:23
+msgid "subscriptions"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:6
+#: forum/skins/default/templates/users/users.html:24
+msgid "Users"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:27
+msgid "recent"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:28
+msgid "oldest"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:29
+msgid "by username"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:35
+#, python-format
+msgid "users matching query %(suser)s:"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:39
+msgid "Nothing found."
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:168 forum/templatetags/extra_tags.py:195
+msgid "reputation points"
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:248
+msgid "2 days ago"
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:250
+msgid "yesterday"
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:252
+#, python-format
+msgid "%(hr)d hour ago"
+msgid_plural "%(hr)d hours ago"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/templatetags/extra_tags.py:254
+#, python-format
+msgid "%(min)d min ago"
+msgid_plural "%(min)d mins ago"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/templatetags/node_tags.py:58
+msgid "permanent link"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:58
+msgid "answer permanent link"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:64
+msgid "retag"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:68
+msgid "reopen"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:70
+msgid "close"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:73 forum/views/commands.py:124
+#: forum/views/commands.py:136
+msgid "flag"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:79
+msgid ""
+"report as offensive (i.e containing spam, advertising, malicious text, etc.)"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:82
+msgid "delete"
+msgstr ""
+
+#: forum/templatetags/question_list_tags.py:57
+msgid "<strong>Newest</strong> questions are shown first. "
+msgstr ""
+
+#: forum/templatetags/question_list_tags.py:58
+msgid "Questions are sorted by the <strong>time of last update</strong>."
+msgstr ""
+
+#: forum/templatetags/question_list_tags.py:59
+msgid "Questions sorted by <strong>number of responses</strong>."
+msgstr ""
+
+#: forum/templatetags/question_list_tags.py:60
+msgid "Questions are sorted by the <strong>number of votes</strong>."
+msgstr ""
+
+#: forum/templatetags/user_tags.py:58 forum/views/readers.py:293
+#, python-format
+msgid "Revision n. %(rev_number)d"
+msgstr ""
+
+#: forum/utils/forms.py:32
+msgid "this field is required"
+msgstr ""
+
+#: forum/utils/forms.py:47
+msgid "choose a username"
+msgstr ""
+
+#: forum/utils/forms.py:52
+msgid "user name is required"
+msgstr ""
+
+#: forum/utils/forms.py:53
+msgid "sorry, this name is taken, please choose another"
+msgstr ""
+
+#: forum/utils/forms.py:54
+msgid "sorry, this name is not allowed, please choose another"
+msgstr ""
+
+#: forum/utils/forms.py:55
+msgid "sorry, there is no user with this name"
+msgstr ""
+
+#: forum/utils/forms.py:56
+msgid "sorry, we have a serious error - user name is taken by several users"
+msgstr ""
+
+#: forum/utils/forms.py:57
+msgid "user name can only consist of letters, empty space and underscore"
+msgstr ""
+
+#: forum/utils/forms.py:105
+msgid "your email address"
+msgstr ""
+
+#: forum/utils/forms.py:106
+msgid "email address is required"
+msgstr ""
+
+#: forum/utils/forms.py:108
+msgid "this email is already used by someone else, please choose another"
+msgstr ""
+
+#: forum/utils/forms.py:133
+msgid "choose password"
+msgstr ""
+
+#: forum/utils/forms.py:134
+msgid "password is required"
+msgstr ""
+
+#: forum/utils/forms.py:137
+msgid "retype password"
+msgstr ""
+
+#: forum/utils/forms.py:138
+msgid "please, retype your password"
+msgstr ""
+
+#: forum/utils/forms.py:139
+msgid "sorry, entered passwords did not match, please try again"
+msgstr ""
+
+#: forum/views/admin.py:47
+#, python-format
+msgid "'%s' settings saved succesfully"
+msgstr ""
+
+#: forum/views/admin.py:141
+msgid "Bootstrap mode enabled"
+msgstr ""
+
+#: forum/views/admin.py:155
+msgid "All values reverted to defaults"
+msgstr ""
+
+#: forum/views/admin.py:171
+msgid "All values recalculated"
+msgstr ""
+
+#: forum/views/auth.py:103 forum/views/auth.py:112
+msgid ""
+"Sorry, these login credentials belong to anoother user. Plese terminate your "
+"current session and try again."
+msgstr ""
+
+#: forum/views/auth.py:105
+msgid "You are already logged in with that user."
+msgstr ""
+
+#: forum/views/auth.py:110
+msgid "These login credentials are already associated with your account."
+msgstr ""
+
+#: forum/views/auth.py:116
+msgid "The new credentials are now associated with your account"
+msgstr ""
+
+#: forum/views/auth.py:157
+msgid ""
+"Oops, something went wrong in the middle of this process. Please try again."
+msgstr ""
+
+#: forum/views/auth.py:219
+msgid "Temporary login link"
+msgstr ""
+
+#: forum/views/auth.py:224
+msgid "An email has been sent with your temporary login key"
+msgstr ""
+
+#: forum/views/auth.py:239
+msgid ""
+"You are logged in with a temporary access key, please take the time to fix "
+"your issue with authentication."
+msgstr ""
+
+#: forum/views/auth.py:245
+msgid "Email Validation"
+msgstr ""
+
+#: forum/views/auth.py:256
+msgid "Thank you, your email is now validated."
+msgstr ""
+
+#: forum/views/auth.py:280
+msgid "Your password was changed"
+msgstr ""
+
+#: forum/views/auth.py:282
+msgid "New password set"
+msgstr ""
+
+#: forum/views/auth.py:315
+#, python-format
+msgid "You removed the association with %s"
+msgstr ""
+
+#: forum/views/auth.py:353
+#, python-format
+msgid "Welcome back %s, you are now logged in"
+msgstr ""
+
+#: forum/views/commands.py:20
+#, python-format
+msgid ""
+"\n"
+"            Sorry, but you don't have enough reputation points to %(action)s."
+"<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:29
+#, python-format
+msgid ""
+"\n"
+"            Sorry but you cannot %(action)s your own post.<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:38
+#, python-format
+msgid ""
+"\n"
+"            Sorry but anonymous users cannot %(action)s.<br />\n"
+"            Please login or create an account <a href'%(signin_url)s'>here</"
+"a>.\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:47
+#, python-format
+msgid ""
+"\n"
+"            Sorry, but you don't have enough %(action)s left for today..<br /"
+">\n"
+"            The limit is %(limit)s per day..<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:57
+#, python-format
+msgid ""
+"\n"
+"            Sorry, but you cannot %(action)s twice the same post.<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:71 forum/views/commands.py:74
+#: forum/views/commands.py:111
+msgid "vote"
+msgid_plural "votes"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/views/commands.py:89
+#, python-format
+msgid ""
+"Sorry but you cannot cancel a vote after %(ndays)d %(tdays)s from the "
+"original vote"
+msgstr ""
+
+#: forum/views/commands.py:90
+msgid "day"
+msgid_plural "days"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/views/commands.py:110
+#, python-format
+msgid "You have %(nvotes)s %(tvotes)s left today."
+msgstr ""
+
+#: forum/views/commands.py:121 forum/views/commands.py:127
+msgid "flag posts"
+msgstr ""
+
+#: forum/views/commands.py:132
+msgid "flags"
+msgstr ""
+
+#: forum/views/commands.py:149 forum/views/commands.py:155
+msgid "like comments"
+msgstr ""
+
+#: forum/views/commands.py:152
+msgid "like"
+msgstr ""
+
+#: forum/views/commands.py:179 forum/views/commands.py:182
+msgid "delete comments"
+msgstr ""
+
+#: forum/views/commands.py:197
+msgid "mark a question as favorite"
+msgstr ""
+
+#: forum/views/commands.py:221 forum/views/commands.py:233
+msgid "comment"
+msgstr ""
+
+#: forum/views/commands.py:224 forum/views/commands.py:351
+msgid "Invalid request"
+msgstr ""
+
+#: forum/views/commands.py:230
+msgid "edit comments"
+msgstr ""
+
+#: forum/views/commands.py:240
+msgid "Comment is empty"
+msgstr ""
+
+#: forum/views/commands.py:265
+msgid "accept answers"
+msgstr ""
+
+#: forum/views/commands.py:271
+msgid "Sorry but only the question author can accept an answer"
+msgstr ""
+
+#: forum/views/commands.py:295 forum/views/commands.py:298
+msgid "delete posts"
+msgstr ""
+
+#: forum/views/meta.py:43
+#, python-format
+msgid "Feedback message from %(site_name)s"
+msgstr ""
+
+#: forum/views/meta.py:46
+msgid "Thanks for the feedback!"
+msgstr ""
+
+#: forum/views/meta.py:53
+msgid "We look forward to hearing your feedback! Please, give it next time :)"
+msgstr ""
+
+#: forum/views/readers.py:64
+msgid "Open questions without an accepted answer"
+msgstr ""
+
+#: forum/views/readers.py:73
+#, python-format
+msgid "Questions tagged <span class=\"tag\">%(tag)s</span>"
+msgstr ""
+
+#: forum/views/readers.py:131
+#, python-format
+msgid "questions matching '%(keywords)s'"
+msgstr ""
+
+#: forum/views/users.py:152
+msgid "user profile"
+msgstr ""
+
+#: forum/views/users.py:152
+msgid "user profile overview"
+msgstr ""
+
+#: forum/views/users.py:186
+msgid "recent user activity"
+msgstr ""
+
+#: forum/views/users.py:186
+msgid "profile - recent activity"
+msgstr ""
+
+#: forum/views/users.py:196
+msgid "profile - votes"
+msgstr ""
+
+#: forum/views/users.py:203
+msgid "user reputation in the community"
+msgstr ""
+
+#: forum/views/users.py:203
+msgid "profile - user reputation"
+msgstr ""
+
+#: forum/views/users.py:214
+msgid "favorite questions"
+msgstr ""
+
+#: forum/views/users.py:214
+msgid "profile - favorite questions"
+msgstr ""
+
+#: forum/views/users.py:220
+msgid "subscription settings"
+msgstr ""
+
+#: forum/views/users.py:220
+msgid "profile - subscriptions"
+msgstr ""
+
+#: forum/views/users.py:230
+msgid "Notifications are now enabled"
+msgstr ""
+
+#: forum/views/users.py:232
+msgid "Notifications are now disabled"
+msgstr ""
+
+#: forum/views/users.py:239
+msgid "New subscription settings are now saved"
+msgstr ""
+
+#: forum/views/writers.py:68
+msgid "uploading images is limited to users with >60 reputation points"
+msgstr ""
+
+#: forum/views/writers.py:70
+msgid "allowed file types are 'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'"
+msgstr ""
+
+#: forum/views/writers.py:72
+#, python-format
+msgid "maximum upload file size is %sM"
+msgstr ""
+
+#: forum/views/writers.py:74
+#, python-format
+msgid ""
+"Error uploading file. Please contact the site administrator. Thank you. %s"
+msgstr ""
+
+#: forum/views/writers.py:85
+msgid "Initial revision"
+msgstr ""
+
+#: forum/views/writers.py:143
+msgid "Retag"
+msgstr ""
+
+#: forum_modules/books/urls.py:7 forum_modules/books/urls.py:8
+#: forum_modules/books/urls.py:9
+msgid "books/"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:17
+#: forum_modules/default_badges/badges.py:24
+#: forum_modules/default_badges/badges.py:31
+#, python-format
+msgid "Asked a question with %s views"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:39
+#: forum_modules/default_badges/badges.py:53
+#: forum_modules/default_badges/badges.py:67
+#, python-format
+msgid "Answer voted up %s times"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:46
+#: forum_modules/default_badges/badges.py:60
+#: forum_modules/default_badges/badges.py:74
+#, python-format
+msgid "Question voted up %s times"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:82
+#: forum_modules/default_badges/badges.py:89
+#, python-format
+msgid "Question favorited by %s users"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:97
+#, python-format
+msgid "Deleted own post with score of %s or higher"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:108
+#, python-format
+msgid "Deleted own post with score of %s or lower"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:120
+msgid "First flagged post"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:127
+msgid "First down vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:134
+msgid "First retag"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:141
+msgid "First up vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:148
+msgid "First edit"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:155
+msgid "First accepted answer on your own question"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:162
+msgid "Completed all user profile fields"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:169
+msgid "First rollback"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:177
+#, python-format
+msgid "Voted %s times"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:184
+#, python-format
+msgid "Left %s comments"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:192
+#, python-format
+msgid "Answered your own question with at least %s up votes"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:205
+msgid "Strunk & White"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:206
+#, python-format
+msgid "Edited %s entries"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:217
+msgid "Asked first question with at least one up vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:228
+msgid "Answered first question with at least one up vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:260
+#, python-format
+msgid "First answer was accepted with at least %s up votes"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:271
+#, python-format
+msgid "Accepted answer and voted up %s times"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:282
+#, python-format
+msgid ""
+"Answered a question more than %(dif_days)s days later with at least %"
+"(up_votes)s votes"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:295
+#, python-format
+msgid "Created a tag used by %s questions"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:6
+msgid "Popular Question views"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:7
+msgid ""
+"\n"
+"Number of question views required to award a Popular Question badge to the "
+"question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:12
+msgid "Notable Question views"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:13
+msgid ""
+"\n"
+"Number of question views required to award a Notable Question badge to the "
+"question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:18
+msgid "Famous Question views"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:19
+msgid ""
+"\n"
+"Number of question views required to award a Famous Question badge to the "
+"question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:24
+msgid "Nice Answer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:25
+msgid ""
+"\n"
+"Number of up votes required to award a Nice Answer badge to the answer "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:30
+msgid "Nice Question up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:31
+msgid ""
+"\n"
+"Number of up votes required to award a Nice Question badge to the question "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:36
+msgid "Good Answer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:37
+msgid ""
+"\n"
+"Number of up votes required to award a Good Answer badge to the answer "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:42
+msgid "Good Question up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:43
+msgid ""
+"\n"
+"Number of up votes required to award a Good Question badge to the question "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:48
+msgid "Great Answer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:49
+msgid ""
+"\n"
+"Number of up votes required to award a Great Answer badge to the answer "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:54
+msgid "Great Question up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:55
+msgid ""
+"\n"
+"Number of up votes required to award a Great Question badge to the question "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:60
+msgid "Favorite Question favorite count"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:61
+msgid ""
+"\n"
+"How many times a question needs to be favorited by other users to award a "
+"Favorite Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:66
+msgid "Stellar Question favorite count"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:67
+msgid ""
+"\n"
+"How many times a question needs to be favorited by other users to award a "
+"Stellar Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:72
+msgid "Disciplined minimum score"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:73
+msgid ""
+"\n"
+"Minimum score a question needs to have to award the Disciplined badge to an "
+"author of a question who deletes it.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:78
+msgid "Peer Pressure maximum score"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:79
+msgid ""
+"\n"
+"Maximum score a question needs to have to award the Peer Pressure badge to "
+"an author of a question who deletes it.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:84
+msgid "Civic Duty votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:85
+msgid ""
+"\n"
+"Number of votes an user needs to cast to be awarded the Civic Duty badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:90
+msgid "Pundit number of comments"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:91
+msgid ""
+"\n"
+"Number of comments an user needs to post to be awarded the Pundit badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:96
+msgid "Self Learner up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:97
+msgid ""
+"\n"
+"Number of up votes an answer from the question author needs to have for the "
+"author to be awarded the Self Learner badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:102
+msgid "Strunk and White updates"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:103
+msgid ""
+"\n"
+"Number of question or answer updates an user needs to make to be awarded the "
+"Strunk & White badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:108
+msgid "Enlightened up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:109
+msgid ""
+"\n"
+"Number of up votes an accepted answer needs to have for the author to be "
+"awarded the Enlightened badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:114
+msgid "Guru up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:115
+msgid ""
+"\n"
+"Number of up votes an accepted answer needs to have for the author to be "
+"awarded the Guru badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:120
+msgid "Necromancer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:121
+msgid ""
+"\n"
+"Number of up votes an answer needs to have for the author to be awarded the "
+"Necromancer badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:126
+msgid "Necromancer difference in days"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:127
+msgid ""
+"\n"
+"Difference in days betwen the posted date of a question and an answer for "
+"the answer author to be awarded the Necromancer badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:132
+msgid "Taxonomist usage count"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:133
+msgid ""
+"\n"
+"How many usages a tag needs to have for the tag creator to be awarded the "
+"Taxonomist badge. \n"
+msgstr ""
+
+#: forum_modules/facebookauth/authentication.py:31
+msgid "Sorry, your Facebook session has expired, please try again"
+msgstr ""
+
+#: forum_modules/facebookauth/authentication.py:33
+msgid ""
+"The authentication with Facebook connect failed due to an invalid signature"
+msgstr ""
+
+#: forum_modules/facebookauth/authentication.py:35
+msgid ""
+"The authentication with Facebook connect failed, cannot find authentication "
+"tokens"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:75
+msgid "Please enter valid username and password (both are case-sensitive)."
+msgstr ""
+
+#: forum_modules/localauth/forms.py:79
+msgid "This account is inactive."
+msgstr ""
+
+#: forum_modules/localauth/forms.py:81
+msgid "Login failed."
+msgstr ""
+
+#: forum_modules/localauth/forms.py:85
+msgid "This user is not a valid user"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:88
+msgid "Please enter username and password"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:90
+msgid "Please enter your password"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:92
+msgid "Please enter user name"
+msgstr ""
+
+#: forum_modules/localauth/urls.py:7
+msgid "local/"
+msgstr ""
+
+#: forum_modules/localauth/views.py:33
+msgid "A validation email has been sent to your email address. "
+msgstr ""
+
+#: forum_modules/oauthauth/consumer.py:33
+msgid "Error, the oauth token is not on the server"
+msgstr ""
+
+#: forum_modules/oauthauth/consumer.py:38
+msgid "Something went wrong! Auth tokens do not match"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:40
+msgid "Sorry, but your input is not a valid OpenId"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:92
+msgid "The OpenId authentication request was canceled"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:94
+msgid "The OpenId authentication failed: "
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:96
+msgid "Setup needed"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:98
+msgid "The OpenId authentication failed with an unknown status: "
+msgstr ""
+
+#: forum_modules/openidauth/templates/openidurl.html:7
+msgid "Enter your OpenId Url"
+msgstr ""
+
+#: forum_modules/project_badges/badges.py:9
+#, python-format
+msgid "Got %s upvotes in a question tagged with \"bug\""
+msgstr ""
+
+#: forum_modules/recaptcha/formfield.py:20
+msgid "Invalid captcha"
+msgstr ""
+
+#: forum_modules/sximporter/importer.py:39
+#, python-format
+msgid "Unknown user %(number)d"
+msgstr ""
+
+#: forum_modules/sximporter/urls.py:8
+msgid "sximporter/"
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:7
+msgid "SX Importer"
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:10
+msgid "Welcome to Stack Exchange dump importer."
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:16
+msgid "Your user id in stack exchange"
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:20
+msgid "Merge users with same user name and email"
+msgstr ""
+
+#: locale/phrases.py:1
+msgid "Test Phrase 1"
+msgstr ""
+
+#: locale/phrases.py:2
+msgid "Test Phrase 2"
+msgstr ""
+
+#: locale/phrases.py:3
+msgid "Test Phrase 3"
+msgstr ""
+
+#: locale/phrases.py:4
+msgid "Test Phrase n"
+msgstr ""
diff --git a/forum/modules/template_loader.py/locale/en/LC_MESSAGES/django.mo b/forum/modules/template_loader.py/locale/en/LC_MESSAGES/django.mo
new file mode 100644 (file)
index 0000000..42da287
Binary files /dev/null and b/forum/modules/template_loader.py/locale/en/LC_MESSAGES/django.mo differ
diff --git a/forum/modules/template_loader.py/locale/en/LC_MESSAGES/django.po b/forum/modules/template_loader.py/locale/en/LC_MESSAGES/django.po
new file mode 100644 (file)
index 0000000..1305ee9
--- /dev/null
@@ -0,0 +1,4552 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+# 
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-04-28 16:53-0400\n"
+"PO-Revision-Date: 2010-05-14 15:33\n"
+"Last-Translator: Rick Ross <rick@dzone.com>\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"
+"X-Translated-Using: django-rosetta 0.5.3\n"
+
+#: forum/const.py:8
+msgid "duplicate question"
+msgstr ""
+
+#: forum/const.py:9
+msgid "question is off-topic or not relevant"
+msgstr ""
+
+#: forum/const.py:10
+msgid "too subjective and argumentative"
+msgstr ""
+
+#: forum/const.py:11
+msgid "is not an answer to the question"
+msgstr ""
+
+#: forum/const.py:12
+msgid "the question is answered, right answer was accepted"
+msgstr ""
+
+#: forum/const.py:13
+msgid "problem is not reproducible or outdated"
+msgstr ""
+
+#: forum/const.py:14
+msgid "question contains offensive inappropriate, or malicious remarks"
+msgstr ""
+
+#: forum/const.py:15
+msgid "spam or advertising"
+msgstr ""
+
+#: forum/const.py:71 forum/skins/default/templates/osqaadmin/index.html:21
+msgid "question"
+msgstr ""
+
+#: forum/const.py:72 forum/skins/default/templates/book.html:110
+#: forum/skins/default/templates/osqaadmin/index.html:26
+msgid "answer"
+msgstr ""
+
+#: forum/const.py:73
+msgid "commented question"
+msgstr ""
+
+#: forum/const.py:74
+msgid "commented answer"
+msgstr ""
+
+#: forum/const.py:75
+msgid "edited question"
+msgstr ""
+
+#: forum/const.py:76
+msgid "edited answer"
+msgstr ""
+
+#: forum/const.py:77
+msgid "received award"
+msgstr "received badge"
+
+#: forum/const.py:78
+msgid "marked best answer"
+msgstr ""
+
+#: forum/const.py:79
+msgid "upvoted"
+msgstr ""
+
+#: forum/const.py:80
+msgid "downvoted"
+msgstr ""
+
+#: forum/const.py:81
+msgid "upvote canceled"
+msgstr ""
+
+#: forum/const.py:82
+msgid "downvote canceled"
+msgstr ""
+
+#: forum/const.py:83
+msgid "deleted question"
+msgstr ""
+
+#: forum/const.py:84
+msgid "deleted answer"
+msgstr ""
+
+#: forum/const.py:85
+msgid "marked offensive"
+msgstr ""
+
+#: forum/const.py:86
+msgid "updated tags"
+msgstr ""
+
+#: forum/const.py:87
+msgid "selected favorite"
+msgstr ""
+
+#: forum/const.py:88
+msgid "completed user profile"
+msgstr ""
+
+#: forum/const.py:89
+msgid "email update sent to user"
+msgstr ""
+
+#: forum/const.py:93
+msgid "question_answered"
+msgstr "answer"
+
+#: forum/const.py:94
+msgid "question_commented"
+msgstr "question comment"
+
+#: forum/const.py:95
+msgid "answer_commented"
+msgstr "answer comment"
+
+#: forum/const.py:96
+msgid "answer_accepted"
+msgstr "answer accepted"
+
+#: forum/const.py:100
+msgid "[closed]"
+msgstr ""
+
+#: forum/const.py:101
+msgid "[deleted]"
+msgstr ""
+
+#: forum/const.py:102
+msgid "initial version"
+msgstr ""
+
+#: forum/const.py:103
+msgid "retagged"
+msgstr ""
+
+#: forum/const.py:111
+msgid "Instantly"
+msgstr ""
+
+#: forum/const.py:112
+msgid "Daily"
+msgstr ""
+
+#: forum/const.py:113
+msgid "Weekly"
+msgstr ""
+
+#: forum/const.py:114
+msgid "No notifications"
+msgstr ""
+
+#: forum/feed.py:18
+msgid " - "
+msgstr ""
+
+#: forum/feed.py:18
+msgid "latest questions"
+msgstr ""
+
+#: forum/forms.py:21 forum/skins/default/templates/answer_edit_tips.html:35
+#: forum/skins/default/templates/answer_edit_tips.html:39
+#: forum/skins/default/templates/question_edit_tips.html:37
+#: forum/skins/default/templates/question_edit_tips.html:42
+msgid "title"
+msgstr ""
+
+#: forum/forms.py:22
+msgid "please enter a descriptive title for your question"
+msgstr ""
+
+#: forum/forms.py:27
+msgid "title must be > 10 characters"
+msgstr ""
+
+#: forum/forms.py:36
+msgid "content"
+msgstr ""
+
+#: forum/forms.py:42
+msgid "question content must be > 10 characters"
+msgstr ""
+
+#: forum/forms.py:52 forum/skins/default/templates/header.html:31
+#: forum/skins/default/templates/header.html:56
+msgid "tags"
+msgstr ""
+
+#: forum/forms.py:54
+msgid "Tags are short keywords, with no spaces within. Up to five tags can be used."
+msgstr ""
+
+#: forum/forms.py:61 forum/skins/default/templates/question_retag.html:43
+msgid "tags are required"
+msgstr ""
+
+#: forum/forms.py:67
+msgid "please use 5 tags or less"
+msgstr ""
+
+#: forum/forms.py:72
+msgid "tags must be shorter than 20 characters"
+msgstr ""
+
+#: forum/forms.py:74
+msgid "please use following characters in tags: letters 'a-z', numbers, and characters '.-_#'"
+msgstr ""
+
+#: forum/forms.py:84
+#: forum/skins/default/templates/post_contributor_info.html:7
+#: forum/skins/default/templates/question_summary_list_roll.html:26
+#: forum/skins/default/templates/question_summary_list_roll.html:38
+msgid "community wiki"
+msgstr ""
+
+#: forum/forms.py:85
+msgid "if you choose community wiki option, the question and answer do not generate points and name of author will not be shown"
+msgstr ""
+
+#: forum/forms.py:101
+msgid "update summary:"
+msgstr ""
+
+#: forum/forms.py:102
+msgid "enter a brief summary of your revision (e.g. fixed spelling, grammar, improved style, this field is optional)"
+msgstr ""
+
+#: forum/forms.py:105
+msgid "Automatically accept user's contributions for the email updates"
+msgstr ""
+
+#: forum/forms.py:118
+msgid "Your name:"
+msgstr ""
+
+#: forum/forms.py:119
+msgid "Email (not shared with anyone):"
+msgstr ""
+
+#: forum/forms.py:120
+msgid "Your message:"
+msgstr ""
+
+#: forum/forms.py:202
+msgid "this email does not have to be linked to gravatar"
+msgstr ""
+
+#: forum/forms.py:204
+msgid "Screen name"
+msgstr ""
+
+#: forum/forms.py:205
+msgid "Real name"
+msgstr ""
+
+#: forum/forms.py:206
+msgid "Website"
+msgstr ""
+
+#: forum/forms.py:207
+msgid "Location"
+msgstr ""
+
+#: forum/forms.py:208
+msgid "Date of birth"
+msgstr ""
+
+#: forum/forms.py:208
+msgid "will not be shown, used to calculate age, format: YYYY-MM-DD"
+msgstr ""
+
+#: forum/forms.py:209 forum/skins/default/templates/account_settings.html:21
+msgid "Profile"
+msgstr ""
+
+#: forum/forms.py:240 forum/forms.py:241
+msgid "this email has already been registered, please use another one"
+msgstr ""
+
+#: forum/subscriptions.py:41
+#, python-format
+msgid "New question on %(app_name)s"
+msgstr ""
+
+#: forum/subscriptions.py:73
+#, fuzzy, python-format
+msgid "New answer to '%(question_title)s'"
+msgstr "Post Your Answer"
+
+#: forum/subscriptions.py:112
+#, python-format
+msgid "New comment on %(question_title)s"
+msgstr ""
+
+#: forum/subscriptions.py:136
+#, python-format
+msgid "An answer to '%(question_title)s' was accepted"
+msgstr ""
+
+#: forum/subscriptions.py:156
+#, python-format
+msgid "%(username)s is a new member on %(app_name)s"
+msgstr ""
+
+#: forum/urls.py:44
+msgid "upfiles/"
+msgstr ""
+
+#: forum/urls.py:49
+msgid "about/"
+msgstr ""
+
+#: forum/urls.py:50
+msgid "faq/"
+msgstr ""
+
+#: forum/urls.py:51
+msgid "privacy/"
+msgstr ""
+
+#: forum/urls.py:52
+msgid "logout/"
+msgstr ""
+
+#: forum/urls.py:53 forum/urls.py:54
+msgid "answers/"
+msgstr ""
+
+#: forum/urls.py:53 forum/urls.py:58 forum/urls.py:98
+#: forum/skins/default/templates/users/info.html:44
+msgid "edit/"
+msgstr ""
+
+#: forum/urls.py:54 forum/urls.py:74
+msgid "revisions/"
+msgstr ""
+
+#: forum/urls.py:55 forum/urls.py:56 forum/urls.py:57 forum/urls.py:58
+#: forum/urls.py:59 forum/urls.py:60 forum/urls.py:61 forum/urls.py:74
+msgid "questions/"
+msgstr ""
+
+#: forum/urls.py:56 forum_modules/books/urls.py:8
+msgid "ask/"
+msgstr ""
+
+#: forum/urls.py:57
+msgid "unanswered/"
+msgstr ""
+
+#: forum/urls.py:59
+msgid "close/"
+msgstr ""
+
+#: forum/urls.py:60
+msgid "reopen/"
+msgstr ""
+
+#: forum/urls.py:61
+msgid "answer/"
+msgstr ""
+
+#: forum/urls.py:63
+msgid "vote/"
+msgstr ""
+
+#: forum/urls.py:64
+#, fuzzy
+msgid "like_comment/"
+msgstr "answer comment"
+
+#: forum/urls.py:65
+#, fuzzy
+msgid "comment/"
+msgstr "post a comment"
+
+#: forum/urls.py:66
+#, fuzzy
+msgid "delete_comment/"
+msgstr "post a comment"
+
+#: forum/urls.py:67
+msgid "accept_answer/"
+msgstr ""
+
+#: forum/urls.py:68
+msgid "mark_favorite/"
+msgstr ""
+
+#: forum/urls.py:69
+msgid "flag/"
+msgstr ""
+
+#: forum/urls.py:70
+msgid "delete/"
+msgstr ""
+
+#: forum/urls.py:71
+msgid "subscribe/"
+msgstr ""
+
+#: forum/urls.py:72
+msgid "matching_tags/"
+msgstr ""
+
+#: forum/urls.py:75
+msgid "command/"
+msgstr ""
+
+#: forum/urls.py:78
+msgid "question/"
+msgstr ""
+
+#: forum/urls.py:79 forum/urls.py:80
+msgid "tags/"
+msgstr ""
+
+#: forum/urls.py:82 forum/urls.py:86
+msgid "mark-tag/"
+msgstr ""
+
+#: forum/urls.py:82
+msgid "interesting/"
+msgstr ""
+
+#: forum/urls.py:86
+msgid "ignored/"
+msgstr ""
+
+#: forum/urls.py:90
+msgid "unmark-tag/"
+msgstr ""
+
+#: forum/urls.py:96 forum/urls.py:98 forum/urls.py:100 forum/urls.py:101
+#: forum/urls.py:102 forum/urls.py:103 forum/urls.py:104 forum/urls.py:105
+#: forum/models/user.py:124
+msgid "users/"
+msgstr ""
+
+#: forum/urls.py:97
+msgid "moderate-user/"
+msgstr ""
+
+#: forum/urls.py:100
+msgid "subscriptions/"
+msgstr ""
+
+#: forum/urls.py:101
+msgid "favorites/"
+msgstr ""
+
+#: forum/urls.py:102
+#, fuzzy
+msgid "reputation/"
+msgstr "karma"
+
+#: forum/urls.py:103
+msgid "votes/"
+msgstr ""
+
+#: forum/urls.py:104
+msgid "recent/"
+msgstr ""
+
+#: forum/urls.py:107 forum/urls.py:108
+msgid "badges/"
+msgstr ""
+
+#: forum/urls.py:109
+msgid "messages/"
+msgstr ""
+
+#: forum/urls.py:109
+msgid "markread/"
+msgstr ""
+
+#: forum/urls.py:111
+msgid "nimda/"
+msgstr ""
+
+#: forum/urls.py:113
+msgid "upload/"
+msgstr ""
+
+#: forum/urls.py:114
+msgid "search/"
+msgstr ""
+
+#: forum/urls.py:115
+msgid "feedback/"
+msgstr ""
+
+#: forum/urls.py:119 forum/urls.py:120 forum/urls.py:121 forum/urls.py:122
+#: forum/urls.py:123 forum/urls.py:124 forum/urls.py:125 forum/urls.py:126
+#: forum/urls.py:127 forum/urls.py:128 forum/urls.py:129 forum/urls.py:130
+#: forum_modules/localauth/urls.py:7
+msgid "account/"
+msgstr ""
+
+#: forum/urls.py:119 forum/urls.py:121 forum/urls.py:122
+msgid "signin/"
+msgstr ""
+
+#: forum/urls.py:120
+msgid "signout/"
+msgstr ""
+
+#: forum/urls.py:123
+msgid "done/"
+msgstr ""
+
+#: forum/urls.py:124 forum_modules/localauth/urls.py:7
+msgid "register/"
+msgstr ""
+
+#: forum/urls.py:125
+msgid "validate/"
+msgstr ""
+
+#: forum/urls.py:126 forum/urls.py:127
+msgid "tempsignin/"
+msgstr ""
+
+#: forum/urls.py:128
+msgid "authsettings/"
+msgstr ""
+
+#: forum/urls.py:129 forum/urls.py:130
+msgid "providers/"
+msgstr ""
+
+#: forum/urls.py:129
+msgid "remove/"
+msgstr ""
+
+#: forum/urls.py:130
+msgid "add/"
+msgstr ""
+
+#: forum/urls.py:133 forum/urls.py:134 forum/urls.py:135 forum/urls.py:136
+#: forum/urls.py:137 forum_modules/sximporter/urls.py:8
+msgid "admin/"
+msgstr ""
+
+#: forum/urls.py:134
+msgid "denormalize/"
+msgstr ""
+
+#: forum/urls.py:135
+msgid "go_bootstrap/"
+msgstr ""
+
+#: forum/urls.py:136
+msgid "go_defaults/"
+msgstr ""
+
+#: forum/authentication/forms.py:21
+#, fuzzy
+msgid "Your account email"
+msgstr "<strong>Your new Email:</strong> (will <strong>not</strong> be shown to anyone, must be valid)"
+
+#: forum/authentication/forms.py:23
+msgid "You cannot leave this field blank"
+msgstr ""
+
+#: forum/authentication/forms.py:24 forum/utils/forms.py:107
+msgid "please enter a valid email address"
+msgstr ""
+
+#: forum/authentication/forms.py:32
+msgid "Sorry, but this email is not on our database."
+msgstr ""
+
+#: forum/authentication/forms.py:40
+msgid "okay, let's try!"
+msgstr ""
+
+#: forum/authentication/forms.py:41
+msgid "no OSQA community email please, thanks"
+msgstr ""
+
+#: forum/authentication/forms.py:44
+msgid "please choose one of the options above"
+msgstr ""
+
+#: forum/authentication/forms.py:51
+msgid "Current password"
+msgstr ""
+
+#: forum/authentication/forms.py:62
+msgid "Old password is incorrect.                     Please enter the correct password."
+msgstr ""
+
+#: forum/management/commands/send_email_alerts.py:56
+msgid "Daily digest"
+msgstr ""
+
+#: forum/middleware/anon_user.py:34
+#, python-format
+msgid "First time here? Check out the <a href=\"%s\">FAQ</a>!"
+msgstr ""
+
+#: forum/models/question.py:30
+msgid "[closed] "
+msgstr ""
+
+#: forum/models/question.py:33
+msgid "[deleted] "
+msgstr ""
+
+#: forum/models/repute.py:13 forum/skins/default/templates/badges.html:53
+msgid "gold"
+msgstr ""
+
+#: forum/models/repute.py:14 forum/skins/default/templates/badges.html:61
+msgid "silver"
+msgstr ""
+
+#: forum/models/repute.py:15 forum/skins/default/templates/badges.html:68
+msgid "bronze"
+msgstr ""
+
+#: forum/models/tag.py:28
+msgid "interesting"
+msgstr ""
+
+#: forum/models/tag.py:28
+msgid "ignored"
+msgstr ""
+
+#: forum/models/user.py:255
+#: forum/skins/default/templates/post_contributor_info.html:19
+msgid "asked"
+msgstr ""
+
+#: forum/models/user.py:257
+#: forum/skins/default/templates/post_contributor_info.html:22
+msgid "answered"
+msgstr ""
+
+#: forum/models/user.py:259
+msgid "marked an answer"
+msgstr ""
+
+#: forum/models/user.py:261
+#, fuzzy
+msgid "edited a question"
+msgstr "Post Your Answer"
+
+#: forum/models/user.py:263
+#, fuzzy
+msgid "commented a question"
+msgstr "list of all questions"
+
+#: forum/models/user.py:265
+#, fuzzy
+msgid "commented an answer"
+msgstr "oldest"
+
+#: forum/models/user.py:267
+#, fuzzy
+msgid "edited an answer"
+msgstr "oldest"
+
+#: forum/models/user.py:269
+#, fuzzy
+msgid "received badge"
+msgstr "received badge"
+
+#: forum/settings/__init__.py:20
+msgid "Badges config"
+msgstr ""
+
+#: forum/settings/__init__.py:20
+msgid "Configure badges on your OSQA site."
+msgstr ""
+
+#: forum/settings/basic.py:9
+msgid "Basic Settings"
+msgstr ""
+
+#: forum/settings/basic.py:9
+msgid "The basic settings for your application"
+msgstr ""
+
+#: forum/settings/basic.py:12
+msgid "Application logo"
+msgstr ""
+
+#: forum/settings/basic.py:13
+#, fuzzy
+msgid "Your site main logo."
+msgstr "<strong>Your new Email:</strong> (will <strong>not</strong> be shown to anyone, must be valid)"
+
+#: forum/settings/basic.py:17
+msgid "Favicon"
+msgstr ""
+
+#: forum/settings/basic.py:18
+msgid "Your site favicon."
+msgstr ""
+
+#: forum/settings/basic.py:22
+msgid "Application title"
+msgstr ""
+
+#: forum/settings/basic.py:23
+msgid "The title of your application that will show in the browsers title bar"
+msgstr ""
+
+#: forum/settings/basic.py:26
+msgid "Application short name"
+msgstr ""
+
+#: forum/settings/basic.py:30
+msgid "Application keywords"
+msgstr ""
+
+#: forum/settings/basic.py:31
+msgid "The meta keywords that will be available through the HTML meta tags."
+msgstr ""
+
+#: forum/settings/basic.py:34
+#, fuzzy
+msgid "Application description"
+msgstr "Gold badge is the highest award in this community. To obtain it have to show profound knowledge and ability in addition to your active participation."
+
+#: forum/settings/basic.py:35
+msgid "The description of your application"
+msgstr ""
+
+#: forum/settings/basic.py:39
+msgid "Application intro"
+msgstr ""
+
+#: forum/settings/basic.py:40
+msgid "The introductory page that is visible in the sidebar for anonymous users."
+msgstr ""
+
+#: forum/settings/basic.py:44
+msgid "Copyright notice"
+msgstr ""
+
+#: forum/settings/basic.py:45
+msgid "The copyright notice visible at the footer of your page."
+msgstr ""
+
+#: forum/settings/basic.py:48
+msgid "Maximum length of comment"
+msgstr ""
+
+#: forum/settings/basic.py:49
+msgid "The maximum length a user can enter for a comment."
+msgstr ""
+
+#: forum/settings/email.py:5
+msgid "Email Settings"
+msgstr ""
+
+#: forum/settings/email.py:5
+msgid "Email server and other email related settings."
+msgstr ""
+
+#: forum/settings/email.py:8
+msgid "Email Server"
+msgstr ""
+
+#: forum/settings/email.py:9
+msgid "The SMTP server through which your application will be sending emails."
+msgstr ""
+
+#: forum/settings/email.py:13
+msgid "Email Port"
+msgstr ""
+
+#: forum/settings/email.py:14
+msgid "The port on which your SMTP server is listening to. Usually this is 25, but can be something else."
+msgstr ""
+
+#: forum/settings/email.py:18
+msgid "Email User"
+msgstr ""
+
+#: forum/settings/email.py:19
+msgid "The username for your SMTP connection."
+msgstr ""
+
+#: forum/settings/email.py:23
+msgid "Email Password"
+msgstr ""
+
+#: forum/settings/email.py:24
+msgid "The password for your SMTP connection."
+msgstr ""
+
+#: forum/settings/email.py:29
+msgid "Use TLS"
+msgstr ""
+
+#: forum/settings/email.py:30
+msgid "Does your SMTP server usFes TLS for authentication."
+msgstr ""
+
+#: forum/settings/email.py:34
+#, fuzzy
+msgid "Site 'from' email address"
+msgstr "Your email <i>(never shared)</i>"
+
+#: forum/settings/email.py:35
+msgid "The address that will show up on the 'from' field on emails sent by your website."
+msgstr ""
+
+#: forum/settings/email.py:39
+#, fuzzy
+msgid "Email subject prefix"
+msgstr "Welcome to the Q&A forum"
+
+#: forum/settings/email.py:40
+msgid "Every email sent through your website will have the subject prefixed by this string. It's usually a good idea to have such a prefix so your users can easilly set up a filter on their email clients."
+msgstr ""
+
+#: forum/settings/extkeys.py:4
+msgid "External Keys"
+msgstr ""
+
+#: forum/settings/extkeys.py:4
+msgid "Keys for various external providers that your application may optionally use."
+msgstr ""
+
+#: forum/settings/extkeys.py:7
+msgid "Google sitemap code"
+msgstr ""
+
+#: forum/settings/extkeys.py:8
+msgid "This is the code you get when you register your site at <a href='https://www.google.com/webmasters/tools/'>Google webmaster central</a>."
+msgstr ""
+
+#: forum/settings/extkeys.py:12
+msgid "Google analytics key"
+msgstr ""
+
+#: forum/settings/extkeys.py:13
+msgid "Your Google analytics key. You can get one at the <a href='http://www.google.com/analytics/'>Google analytics official website</a>"
+msgstr ""
+
+#: forum/settings/forms.py:40
+#, fuzzy
+msgid "Change this:"
+msgstr "Change Email"
+
+#: forum/settings/minrep.py:4
+#, fuzzy
+msgid "Minimum reputation config"
+msgstr "karma"
+
+#: forum/settings/minrep.py:4
+msgid "Configure the minimum reputation required to perform certain actions on your site."
+msgstr ""
+
+#: forum/settings/minrep.py:7
+msgid "Minimum reputation to vote up"
+msgstr ""
+
+#: forum/settings/minrep.py:8
+msgid "The minimum reputation an user must have to be allowed to vote up."
+msgstr ""
+
+#: forum/settings/minrep.py:11
+#, fuzzy
+msgid "Minimum reputation to vote down"
+msgstr "user karma"
+
+#: forum/settings/minrep.py:12
+msgid "The minimum reputation an user must have to be allowed to vote down."
+msgstr ""
+
+#: forum/settings/minrep.py:15
+msgid "Minimum reputation to flag a post"
+msgstr ""
+
+#: forum/settings/minrep.py:16
+msgid "The minimum reputation an user must have to be allowed to flag a post."
+msgstr ""
+
+#: forum/settings/minrep.py:19
+#, fuzzy
+msgid "Minimum reputation to comment"
+msgstr "user karma"
+
+#: forum/settings/minrep.py:20
+msgid "The minimum reputation an user must have to be allowed to comment a post."
+msgstr ""
+
+#: forum/settings/minrep.py:23
+#, fuzzy
+msgid "Minimum reputation to like a comment"
+msgstr "user karma"
+
+#: forum/settings/minrep.py:24
+msgid "The minimum reputation an user must have to be allowed to \"like\" a comment."
+msgstr ""
+
+#: forum/settings/minrep.py:27
+msgid "Minimum reputation to upload"
+msgstr ""
+
+#: forum/settings/minrep.py:28
+msgid "The minimum reputation an user must have to be allowed to upload a file."
+msgstr ""
+
+#: forum/settings/minrep.py:31
+msgid "Minimum reputation to close own question"
+msgstr ""
+
+#: forum/settings/minrep.py:32
+msgid "The minimum reputation an user must have to be allowed to close his own question."
+msgstr ""
+
+#: forum/settings/minrep.py:35
+msgid "Minimum reputation to reopen own question"
+msgstr ""
+
+#: forum/settings/minrep.py:36
+msgid "The minimum reputation an user must have to be allowed to reopen his own question."
+msgstr ""
+
+#: forum/settings/minrep.py:39
+msgid "Minimum reputation to retag others questions"
+msgstr ""
+
+#: forum/settings/minrep.py:40
+msgid "The minimum reputation an user must have to be allowed to retag others questions."
+msgstr ""
+
+#: forum/settings/minrep.py:43
+msgid "Minimum reputation to edit wiki posts"
+msgstr ""
+
+#: forum/settings/minrep.py:44
+msgid "The minimum reputation an user must have to be allowed to edit community wiki posts."
+msgstr ""
+
+#: forum/settings/minrep.py:47
+msgid "Minimum reputation to edit others posts"
+msgstr ""
+
+#: forum/settings/minrep.py:48
+msgid "The minimum reputation an user must have to be allowed to edit others posts."
+msgstr ""
+
+#: forum/settings/minrep.py:51
+msgid "Minimum reputation to close others posts"
+msgstr ""
+
+#: forum/settings/minrep.py:52
+msgid "The minimum reputation an user must have to be allowed to close others posts."
+msgstr ""
+
+#: forum/settings/minrep.py:55
+#, fuzzy
+msgid "Minimum reputation to delete comments"
+msgstr "user karma"
+
+#: forum/settings/minrep.py:56
+msgid "The minimum reputation an user must have to be allowed to delete comments."
+msgstr ""
+
+#: forum/settings/minrep.py:59
+msgid "Minimum reputation to view offensive flags"
+msgstr ""
+
+#: forum/settings/minrep.py:60
+msgid "The minimum reputation an user must have to view offensive flags."
+msgstr ""
+
+#: forum/settings/repgain.py:4
+msgid "Reputation gains and losses config"
+msgstr ""
+
+#: forum/settings/repgain.py:4
+msgid "Configure the reputation points a user may gain or lose upon certain actions."
+msgstr ""
+
+#: forum/settings/repgain.py:7
+#, fuzzy
+msgid "Initial reputation"
+msgstr "karma"
+
+#: forum/settings/repgain.py:8
+msgid "The initial reputation an user gets when he first signs in."
+msgstr ""
+
+#: forum/settings/repgain.py:12
+msgid "Maximum reputation a user can gain in one day for being upvoted."
+msgstr ""
+
+#: forum/settings/repgain.py:15
+msgid "Rep gain by upvoted"
+msgstr ""
+
+#: forum/settings/repgain.py:16
+msgid "Reputation a user gains for having one of his posts up voted."
+msgstr ""
+
+#: forum/settings/repgain.py:19
+msgid "Rep lost bu upvote canceled"
+msgstr ""
+
+#: forum/settings/repgain.py:20
+msgid "Reputation a user loses for having one of the upvotes on his posts canceled."
+msgstr ""
+
+#: forum/settings/repgain.py:23
+msgid "Rep lost by downvoted"
+msgstr ""
+
+#: forum/settings/repgain.py:24
+msgid "Reputation a user loses for having one of his posts down voted."
+msgstr ""
+
+#: forum/settings/repgain.py:27
+msgid "Rep lost by downvoting"
+msgstr ""
+
+#: forum/settings/repgain.py:28
+msgid "Reputation a user loses for down voting a post."
+msgstr ""
+
+#: forum/settings/repgain.py:31
+msgid "Rep gain by downvote canceled"
+msgstr ""
+
+#: forum/settings/repgain.py:32
+msgid "Reputation a user gains for having one of the downvotes on his posts canceled."
+msgstr ""
+
+#: forum/settings/repgain.py:35
+msgid "Rep gain by canceling downvote"
+msgstr ""
+
+#: forum/settings/repgain.py:36
+msgid "Reputation a user gains for canceling a downvote."
+msgstr ""
+
+#: forum/settings/repgain.py:39
+msgid "Rep gain by accepted answer"
+msgstr ""
+
+#: forum/settings/repgain.py:40
+msgid "Reputation a user gains for having one of his answers accepted."
+msgstr ""
+
+#: forum/settings/repgain.py:43
+msgid "Rep lost by accepted canceled"
+msgstr ""
+
+#: forum/settings/repgain.py:44
+msgid "Reputation a user loses for having one of his accepted answers canceled."
+msgstr ""
+
+#: forum/settings/repgain.py:47
+msgid "Rep gain by accepting answer"
+msgstr ""
+
+#: forum/settings/repgain.py:48
+msgid "Reputation a user gains for accepting an answer to one of his questions."
+msgstr ""
+
+#: forum/settings/repgain.py:51
+msgid "Rep lost by canceling accepted"
+msgstr ""
+
+#: forum/settings/repgain.py:52
+msgid "Reputation a user loses by canceling an accepted answer."
+msgstr ""
+
+#: forum/settings/repgain.py:55
+msgid "Rep lost by post flagged"
+msgstr ""
+
+#: forum/settings/repgain.py:56
+msgid "Reputation a user loses by having one of his posts flagged."
+msgstr ""
+
+#: forum/settings/repgain.py:59
+msgid "Rep lost by post flagged and hidden"
+msgstr ""
+
+#: forum/settings/repgain.py:60
+msgid "Reputation a user loses by having the last revision of one of his posts flagged the enough number of times to hide the post."
+msgstr ""
+
+#: forum/settings/repgain.py:63
+msgid "Rep lost by post flagged and deleted"
+msgstr ""
+
+#: forum/settings/repgain.py:64
+msgid "Reputation a user loses by having the last revision of one of his posts flagged the enough number of times to delete the post."
+msgstr ""
+
+#: forum/settings/upload.py:5
+msgid "File upload settings"
+msgstr ""
+
+#: forum/settings/upload.py:5
+msgid "File uploads related settings."
+msgstr ""
+
+#: forum/settings/upload.py:8
+msgid "Uploaded files folder"
+msgstr ""
+
+#: forum/settings/upload.py:9
+msgid "The filesystem path where uploaded files will be stored. Please note that this folder must exist."
+msgstr ""
+
+#: forum/settings/upload.py:12
+msgid "Uploaded files alias"
+msgstr ""
+
+#: forum/settings/upload.py:13
+msgid "The url alias for uploaded files. Notice that if you change this setting, you'll need to restart your site."
+msgstr ""
+
+#: forum/settings/upload.py:16
+msgid "Max file size"
+msgstr ""
+
+#: forum/settings/upload.py:17
+msgid "The maximum allowed file size for uploads in mb."
+msgstr ""
+
+#: forum/settings/voting.py:4
+msgid "Voting rules"
+msgstr ""
+
+#: forum/settings/voting.py:4
+msgid "Configure the voting rules on your site."
+msgstr ""
+
+#: forum/settings/voting.py:7
+msgid "Maximum votes per day"
+msgstr ""
+
+#: forum/settings/voting.py:8
+msgid "The maximum number of votes an user can cast per day."
+msgstr ""
+
+#: forum/settings/voting.py:11
+msgid "Start warning about votes left"
+msgstr ""
+
+#: forum/settings/voting.py:12
+msgid "From how many votes left should an user start to be warned about it."
+msgstr ""
+
+#: forum/settings/voting.py:15
+msgid "Maximum flags per day"
+msgstr ""
+
+#: forum/settings/voting.py:16
+msgid "The maximum number of times an can flag a post per day."
+msgstr ""
+
+#: forum/settings/voting.py:19
+msgid "Flag count to hide post"
+msgstr ""
+
+#: forum/settings/voting.py:20
+msgid "How many times a post needs to be flagged to be hidden from the main page."
+msgstr ""
+
+#: forum/settings/voting.py:23
+msgid "Flag count to delete post"
+msgstr ""
+
+#: forum/settings/voting.py:24
+msgid "How many times a post needs to be flagged to be deleted."
+msgstr ""
+
+#: forum/settings/voting.py:27
+msgid "Days to cancel a vote"
+msgstr ""
+
+#: forum/settings/voting.py:28
+msgid "How many days an user can cancel a vote after he originaly casted it."
+msgstr ""
+
+#: forum/skins/default/templates/404.html:24
+msgid "Sorry, could not find the page you requested."
+msgstr ""
+
+#: forum/skins/default/templates/404.html:26
+msgid "This might have happened for the following reasons:"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:28
+msgid "this question or answer has been deleted;"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:29
+msgid "url has error - please check it;"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:30
+msgid "the page you tried to visit is protected or you don't have sufficient points, see"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:31
+msgid "if you believe this error 404 should not have occured, please"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:32
+msgid "report this problem"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:41
+#: forum/skins/default/templates/500.html:27
+msgid "back to previous page"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:42
+msgid "see all questions"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:43
+msgid "see all tags"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:22
+msgid "sorry, system error"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:24
+msgid "system error log is recorded, error will be fixed as soon as possible"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:25
+msgid "please report the error to the site administrators if you wish"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:28
+msgid "see latest questions"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:29
+msgid "see tags"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:12
+#: forum/skins/default/templates/book.html:105
+#: forum/skins/default/templates/question_summary_list_roll.html:14
+#: forum/skins/default/templates/question_list/item.html:10
+#: forum/views/commands.py:82
+msgid "votes"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:14
+msgid "this answer has been accepted to be correct"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:16
+#: forum/skins/default/templates/question_summary_list_roll.html:13
+#: forum/skins/default/templates/question_list/item.html:14
+msgid "answers"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:20
+#: forum/skins/default/templates/book.html:115
+#: forum/skins/default/templates/question_summary_list_roll.html:15
+#: forum/skins/default/templates/question_list/item.html:18
+msgid "views"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:34
+#: forum/skins/default/templates/question.html:234
+#: forum/skins/default/templates/question_summary_list_roll.html:52
+#: forum/skins/default/templates/tags.html:49
+#: forum/skins/default/templates/question_list/item.html:29
+msgid "see questions tagged"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:34
+#: forum/skins/default/templates/book.html:125
+#: forum/skins/default/templates/question.html:234
+#: forum/skins/default/templates/question_summary_list_roll.html:52
+#: forum/skins/default/templates/tags.html:49
+#: forum/skins/default/templates/question_list/item.html:29
+msgid "using tags"
+msgstr ""
+
+#: forum/skins/default/templates/about.html:5
+#: forum/skins/default/templates/about.html:9
+msgid "About"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:4
+msgid "Account functions"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:29
+#: forum/skins/default/templates/auth/auth_settings.html:31
+msgid "Change password"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:30
+msgid "Give your  account a new password."
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:32
+msgid "Change email "
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:33
+msgid "Add or update the email address associated with your account."
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:35
+msgid "Change OpenID"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:36
+msgid "Change openid associated to your account"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:39
+msgid "Delete account"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:40
+msgid "Erase your username and all your data from website"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:5
+#: forum/skins/default/templates/answer_edit.html:39
+msgid "Edit answer"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:18
+#: forum/skins/default/templates/answer_edit.html:21
+#: forum/skins/default/templates/ask.html:19
+#: forum/skins/default/templates/ask.html:22
+#: forum/skins/default/templates/question_edit.html:19
+#: forum/skins/default/templates/question_edit.html:22
+msgid "hide preview"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:21
+#: forum/skins/default/templates/ask.html:22
+#: forum/skins/default/templates/question_edit.html:22
+msgid "show preview"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:39
+#: forum/skins/default/templates/question_edit.html:63
+#: forum/skins/default/templates/question_retag.html:56
+#: forum/skins/default/templates/revisions_answer.html:36
+#: forum/skins/default/templates/revisions_question.html:35
+msgid "back"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:44
+#: forum/skins/default/templates/question_edit.html:68
+#: forum/skins/default/templates/revisions_answer.html:50
+#: forum/skins/default/templates/revisions_question.html:49
+msgid "revision"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:47
+#: forum/skins/default/templates/question_edit.html:72
+msgid "select revision"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:54
+#: forum/skins/default/templates/ask.html:93
+#: forum/skins/default/templates/question.html:184
+#: forum/skins/default/templates/question_edit.html:89
+msgid "Toggle the real time Markdown editor preview"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:54
+#: forum/skins/default/templates/ask.html:93
+#: forum/skins/default/templates/question.html:185
+#: forum/skins/default/templates/question_edit.html:89
+msgid "toggle preview"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:63
+#: forum/skins/default/templates/question_edit.html:115
+#: forum/skins/default/templates/question_retag.html:77
+msgid "Save edit"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:64
+#: forum/skins/default/templates/close.html:29
+#: forum/skins/default/templates/feedback.html:50
+#: forum/skins/default/templates/question_edit.html:116
+#: forum/skins/default/templates/question_retag.html:78
+#: forum/skins/default/templates/reopen.html:30
+#: forum/skins/default/templates/users/edit.html:87
+msgid "Cancel"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:4
+msgid "answer tips"
+msgstr "Tips"
+
+#: forum/skins/default/templates/answer_edit_tips.html:7
+msgid "please make your answer relevant to this community"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:10
+msgid "try to give an answer, rather than engage into a discussion"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:13
+msgid "please try to provide details"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:16
+#: forum/skins/default/templates/question_edit_tips.html:18
+msgid "be clear and concise"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:20
+#: forum/skins/default/templates/question_edit_tips.html:22
+msgid "see frequently asked questions"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:26
+#: forum/skins/default/templates/question_edit_tips.html:28
+msgid "Markdown tips"
+msgstr "Markdown basics"
+
+#: forum/skins/default/templates/answer_edit_tips.html:29
+#: forum/skins/default/templates/question_edit_tips.html:31
+msgid "*italic* or __italic__"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:32
+#: forum/skins/default/templates/question_edit_tips.html:34
+msgid "**bold** or __bold__"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:35
+#: forum/skins/default/templates/question_edit_tips.html:37
+msgid "link"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:35
+#: forum/skins/default/templates/answer_edit_tips.html:39
+#: forum/skins/default/templates/question_edit_tips.html:37
+#: forum/skins/default/templates/question_edit_tips.html:42
+msgid "text"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:39
+#: forum/skins/default/templates/question_edit_tips.html:42
+msgid "image"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:43
+#: forum/skins/default/templates/question_edit_tips.html:46
+msgid "numbered list:"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:48
+#: forum/skins/default/templates/question_edit_tips.html:51
+msgid "basic HTML tags are also supported"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:52
+#: forum/skins/default/templates/question_edit_tips.html:55
+msgid "learn more about Markdown"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:5
+#: forum/skins/default/templates/ask.html:57
+msgid "Ask a question"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:64
+msgid "login to post question info"
+msgstr "<span class=\"strong big\">You are welcome to start submitting your question anonymously</span>. When you submit the post, you will be redirected to the login/signup page. Your question will be saved in the current session and will be published after you log in. Login/signup process is very simple. Login takes about 30 seconds, initial signup takes a minute or less."
+
+#: forum/skins/default/templates/ask.html:70
+#, python-format
+msgid ""
+"must have valid %(email)s to post, \n"
+"                            see %(email_validation_faq_url)s\n"
+"                            "
+msgstr "<span class='strong big'>Looks like your email address, %(email)s has not yet been validated.</span> To post messages you must verify your email, please see <a href='%(email_validation_faq_url)s'>more details here</a>.<br>You can submit your question now and validate email after that. Your question will saved as pending meanwhile. "
+
+#: forum/skins/default/templates/ask.html:108
+msgid "(required)"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:115
+msgid "Login/signup to post your question"
+msgstr "Login/Signup to Post"
+
+#: forum/skins/default/templates/ask.html:117
+msgid "Ask your question"
+msgstr "Ask Your Question"
+
+#: forum/skins/default/templates/badge.html:6
+#: forum/skins/default/templates/badge.html:17
+msgid "Badge"
+msgstr ""
+
+#: forum/skins/default/templates/badge.html:26
+msgid "The users have been awarded with badges:"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:6
+msgid "Badges summary"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:17
+msgid "Badges"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:21
+msgid "Community gives you awards for your questions, answers and votes."
+msgstr "If your questions and answers are highly voted, your contribution to this Q&amp;A community will be recognized with the variety of badges."
+
+#: forum/skins/default/templates/badges.html:22
+#, python-format
+msgid ""
+"Below is the list of available badges and number \n"
+"    of times each type of badge has been awarded. Give us feedback at %(feedback_faq_url)s.\n"
+"    "
+msgstr "Currently badges differ only by their level: <strong>gold</strong>, <strong>silver</strong> and <strong>bronze</strong> (their meanings are described on the right). In the future there will be many types of badges at each level. <strong>Please give us your <a href='%(feedback_faq_url)s'>feedback</a></strong> - what kinds of badges would you like to see and suggest the activity for which those badges might be awarded."
+
+#: forum/skins/default/templates/badges.html:50
+msgid "Community badges"
+msgstr "Badge levels"
+
+#: forum/skins/default/templates/badges.html:56
+msgid "gold badge description"
+msgstr "Gold badge is the highest award in this community. To obtain it have to show profound knowledge and ability in addition to your active participation."
+
+#: forum/skins/default/templates/badges.html:64
+msgid "silver badge description"
+msgstr "Obtaining silver badge requires significant patience. If you have received one, that means you have greatly contributed to this community."
+
+#: forum/skins/default/templates/badges.html:67
+msgid "bronze badge: often given as a special honor"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:71
+msgid "bronze badge description"
+msgstr "If you are an active participant in this community, you will be recognized with this badge."
+
+#: forum/skins/default/templates/book.html:7
+msgid "reading channel"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:26
+msgid "[author]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:30
+msgid "[publisher]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:34
+msgid "[publication date]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:38
+msgid "[price]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:39
+msgid "currency unit"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:42
+msgid "[pages]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:43
+msgid "pages abbreviation"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:46
+msgid "[tags]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:56
+msgid "author blog"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:62
+msgid "book directory"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:66
+msgid "buy online"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:79
+msgid "reader questions"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:82
+msgid "ask the author"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:88
+#: forum/skins/default/templates/book.html:93
+msgid "this question was selected as favorite"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:88
+#: forum/skins/default/templates/book.html:93
+msgid "number of times"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:108
+msgid "the answer has been accepted to be correct"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:147
+msgid "subscribe to book RSS feed"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:147
+msgid "subscribe to the questions feed"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:6
+#: forum/skins/default/templates/close.html:16
+msgid "Close question"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:19
+msgid "Close the question"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:25
+msgid "Reasons"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:28
+msgid "OK to close"
+msgstr ""
+
+#: forum/skins/default/templates/email_base.html:31
+msgid "home"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:11
+msgid "Frequently Asked Questions "
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:16
+msgid "What kinds of questions can I ask here?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:17
+msgid "Most importantly - questions should be <strong>relevant</strong> to this community."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:18
+msgid "Before asking the question - please make sure to use search to see whether your question has alredy been answered."
+msgstr "Before you ask - please make sure to search for a similar question. You can search questions by their title or tags."
+
+#: forum/skins/default/templates/faq.html:21
+msgid "What questions should I avoid asking?"
+msgstr "What kinds of questions should be avoided?"
+
+#: forum/skins/default/templates/faq.html:22
+msgid "Please avoid asking questions that are not relevant to this community, too subjective and argumentative."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:27
+msgid "What should I avoid in my answers?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:28
+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 "is a <strong>question and answer</strong> site - <strong>it is not a discussion group</strong>. Please avoid holding debates in your answers as they tend to dilute the essense of questions and answers. For the brief discussions please use commenting facility."
+
+#: forum/skins/default/templates/faq.html:32
+msgid "Who moderates this community?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:33
+msgid "The short answer is: <strong>you</strong>."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:34
+msgid "This website is moderated by the users."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:35
+msgid "The reputation system allows users earn the authorization to perform a variety of moderation tasks."
+msgstr "Karma system allows users to earn rights to perform a variety of moderation tasks"
+
+#: forum/skins/default/templates/faq.html:40
+msgid "How does reputation system work?"
+msgstr "How does karma system work?"
+
+#: forum/skins/default/templates/faq.html:41
+msgid "Rep system summary"
+msgstr "When a question or answer is upvoted, the user who posted them will gain some points, which are called \"karma points\". These points serve as a rough measure of the community trust to him/her. Various moderation tasks are gradually assigned to the users based on those points."
+
+#: forum/skins/default/templates/faq.html:42
+msgid "For example, if you ask an interesting question or give a helpful answer, your input will be upvoted. On the other hand if the answer is misleading - it will be downvoted. Each vote in favor will generate <strong>10</strong> points, each vote against will subtract <strong>2</strong> points. There is a limit of <strong>200</strong> points that can be accumulated per question or answer. The table below explains reputation point requirements for each type of moderation task."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:53
+#: forum/skins/default/templates/users/votes.html:15
+#: forum/views/commands.py:77
+msgid "upvote"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:57
+msgid "use tags"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:62
+msgid "add comments"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:66
+#: forum/skins/default/templates/users/votes.html:17
+#: forum/views/commands.py:77
+msgid "downvote"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:69
+msgid "open and close own questions"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:73
+msgid "retag questions"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:78
+msgid "edit community wiki questions"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:83
+msgid "edit any answer"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:87
+msgid "open any closed question"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:91
+msgid "delete any comment"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:95
+msgid "delete any questions and answers and perform other moderation tasks"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:103
+msgid "how to validate email title"
+msgstr "How to validate email and why?"
+
+#: forum/skins/default/templates/faq.html:105
+#, python-format
+msgid "how to validate email info with %(send_email_key_url)s %(gravatar_faq_url)s"
+msgstr "<form style='margin:0;padding:0;' action='%(send_email_key_url)s'><p><span class=\"bigger strong\">How?</span> If you have just set or changed your email address - <strong>check your email and click the included link</strong>.<br>The link contains a key generated specifically for you. You can also <button style='display:inline' type='submit'><strong>get a new key</strong></button> and check your email again.</p></form><span class=\"bigger strong\">Why?</span> Email validation is required to make sure that <strong>only you can post messages</strong> on your behalf and to <strong>minimize spam</strong> posts.<br>With email you can <strong>subscribe for updates</strong> on the most interesting questions. Also, when you sign up for the first time - create a unique <a href='%(gravatar_faq_url)s'><strong>gravatar</strong></a> personal image.</p>"
+
+#: forum/skins/default/templates/faq.html:110
+msgid "what is gravatar"
+msgstr "What is gravatar?"
+
+#: forum/skins/default/templates/faq.html:111
+msgid "gravatar faq info"
+msgstr "<strong>Gravatar</strong> means <strong>g</strong>lobally <strong>r</strong>ecognized <strong>avatar</strong> - your unique avatar image associated with your email address. It's simply a picture that shows next to your posts on the websites that support gravatar protocol. By default gravar appears as a square filled with a snowflake-like figure. You can <strong>set your image</strong> at <a href='http://gravatar.com'><strong>gravatar.com</strong></a>"
+
+#: forum/skins/default/templates/faq.html:114
+msgid "To register, do I need to create new password?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:115
+msgid "No, you don't have to. You can login through any service that supports OpenID, e.g. Google, Yahoo, AOL, etc."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:116
+msgid "Login now!"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:121
+msgid "Why other people can edit my questions/answers?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:122
+msgid "Goal of this site is..."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:122
+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 ""
+
+#: forum/skins/default/templates/faq.html:123
+msgid "If this approach is not for you, we respect your choice."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:127
+msgid "Still have questions?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:128
+#, python-format
+msgid "Please ask your question at %(ask_question_url)s, help make our community better!"
+msgstr "Please <a href='%(ask_question_url)s'>ask</a> your question, help make our community better!"
+
+#: forum/skins/default/templates/faq.html:130
+#: forum/skins/default/templates/header.html:30
+#: forum/skins/default/templates/header.html:55 forum/views/readers.py:76
+msgid "questions"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:130
+msgid "."
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:6
+msgid "Feedback"
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:11
+msgid "Give us your feedback!"
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:17
+#, python-format
+msgid ""
+"\n"
+"            <span class='big strong'>Dear %(user_name)s</span>, we look forward to hearing your feedback. \n"
+"            Please type and send us your message below.\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:24
+msgid ""
+"\n"
+"            <span class='big strong'>Dear visitor</span>, we look forward to hearing your feedback.\n"
+"            Please type and send us your message below.\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:41
+msgid "(this field is required)"
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:49
+msgid "Send Feedback"
+msgstr ""
+
+#: forum/skins/default/templates/footer.html:7
+#: forum/skins/default/templates/header.html:16
+#: forum/skins/default/templates/index.html:12
+msgid "about"
+msgstr ""
+
+#: forum/skins/default/templates/footer.html:8
+#: forum/skins/default/templates/header.html:17
+#: forum/skins/default/templates/index.html:13
+#: forum/skins/default/templates/question_edit_tips.html:22
+msgid "faq"
+msgstr ""
+
+#: forum/skins/default/templates/footer.html:9
+msgid "privacy policy"
+msgstr "privacy"
+
+#: forum/skins/default/templates/footer.html:18
+msgid "give feedback"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:9
+msgid "administration"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:12
+msgid "logout"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:14
+msgid "login"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:24
+msgid "back to home page"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:32
+#: forum/skins/default/templates/header.html:57
+msgid "users"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:33
+#: forum/skins/default/templates/users/signature.html:9
+#: forum/skins/default/templates/users/signature.html:15
+#: forum/skins/default/templates/users/signature.html:21
+#: forum/templatetags/extra_tags.py:167 forum/templatetags/extra_tags.py:196
+msgid "badges"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:34
+msgid "unanswered questions"
+msgstr "unanswered"
+
+#: forum/skins/default/templates/header.html:36
+msgid "ask a question"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:51
+msgid "search"
+msgstr ""
+
+#: forum/skins/default/templates/index.html:9
+#, fuzzy
+msgid "welcome to "
+msgstr "Welcome to Q&amp;A forum"
+
+#: forum/skins/default/templates/logout.html:6
+#: forum/skins/default/templates/logout.html:16
+msgid "Logout"
+msgstr ""
+
+#: forum/skins/default/templates/logout.html:19
+msgid "As a registered user you can login with your OpenID, log out of the site or permanently remove your account."
+msgstr "Clicking <strong>Logout</strong> will log you out from the forum, but will not sign you off from your OpenID provider.</p><p>If you wish to sign off completely - please make sure to log out from your OpenID provider as well."
+
+#: forum/skins/default/templates/logout.html:20
+msgid "Logout now"
+msgstr "Logout Now"
+
+#: forum/skins/default/templates/notarobot.html:3
+msgid "Please prove that you are a Human Being"
+msgstr ""
+
+#: forum/skins/default/templates/notarobot.html:10
+msgid "I am a Human Being"
+msgstr ""
+
+#: forum/skins/default/templates/pagesize.html:6
+msgid "posts per page"
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:6
+#: forum/skins/default/templates/paginator.html:7
+msgid "previous"
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:19
+msgid "current page"
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:22
+#: forum/skins/default/templates/paginator.html:29
+msgid "page number "
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:22
+#: forum/skins/default/templates/paginator.html:29
+msgid "number - make blank in english"
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:33
+msgid "next page"
+msgstr ""
+
+#: forum/skins/default/templates/post_contributor_info.html:9
+#, python-format
+msgid ""
+"\n"
+"                one revision\n"
+"            "
+msgid_plural ""
+"\n"
+"                %(rev_count)s revisions\n"
+"            "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/post_contributor_info.html:24
+msgid "posted"
+msgstr ""
+
+#: forum/skins/default/templates/post_contributor_info.html:45
+msgid "updated"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:6
+#: forum/skins/default/templates/privacy.html:11
+msgid "Privacy policy"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:15
+msgid "general message about privacy"
+msgstr "Respecting users privacy is an important core principle of this Q&amp;A forum. Information on this page details how this forum protects your privacy, and what type of information is collected."
+
+#: forum/skins/default/templates/privacy.html:18
+msgid "Site Visitors"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:20
+msgid "what technical information is collected about visitors"
+msgstr "Information on question views, revisions of questions and answers - both times and content are recorded for each user in order to correctly count number of views, maintain data integrity and report relevant updates."
+
+#: forum/skins/default/templates/privacy.html:23
+msgid "Personal Information"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:25
+msgid "details on personal information policies"
+msgstr "Members of this community may choose to display personally identifiable information in their profiles. Forum will never display such information without a request from the user."
+
+#: forum/skins/default/templates/privacy.html:28
+msgid "Other Services"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:30
+msgid "details on sharing data with third parties"
+msgstr "None of the data that is not openly shown on the forum by the choice of the user is shared with any third party."
+
+#: forum/skins/default/templates/privacy.html:35
+msgid "cookie policy details"
+msgstr "Forum software relies on the internet cookie technology to keep track of user sessions. Cookies must be enabled in your browser so that forum can work for you."
+
+#: forum/skins/default/templates/privacy.html:37
+msgid "Policy Changes"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:38
+msgid "how privacy policies can be changed"
+msgstr "These policies may be adjusted to improve protection of user's privacy. Whenever such changes occur, users will be notified via the internal messaging system. "
+
+#: forum/skins/default/templates/question.html:70
+#: forum/skins/default/templates/sidebar/recent_tags.html:9
+#, python-format
+msgid "see questions tagged '%(tagname)s'"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:87
+#, python-format
+msgid "The question has been closed for the following reason \"%(close_reason)s\" by"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:89
+#, python-format
+msgid "close date %(closed_at)s"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:97
+#, python-format
+msgid ""
+"\n"
+"                    One Answer:\n"
+"                    "
+msgid_plural ""
+"\n"
+"                    %(counter)s Answers:\n"
+"                    "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/question.html:105
+msgid "oldest answers will be shown first"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:105
+msgid "oldest answers"
+msgstr "oldest"
+
+#: forum/skins/default/templates/question.html:107
+msgid "newest answers will be shown first"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:107
+msgid "newest answers"
+msgstr "newest"
+
+#: forum/skins/default/templates/question.html:109
+msgid "most voted answers will be shown first"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:109
+msgid "popular answers"
+msgstr "most voted"
+
+#: forum/skins/default/templates/question.html:157
+msgid "Your answer"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:159
+msgid "Be the first one to answer this question!"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:165
+msgid "you can answer anonymously and then login"
+msgstr "<span class='strong big'>Please start posting your answer anonymously</span> - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a <strong>substantial answer</strong>, for discussions, <strong>please use comments</strong> and <strong>please do remember to vote</strong> (after you log in)!"
+
+#: forum/skins/default/templates/question.html:169
+msgid "answer your own question only to give an answer"
+msgstr "<span class='big strong'>You are welcome to answer your own question</span>, but please make sure to give an <strong>answer</strong>. Remember that you can always <strong>revise your original question</strong>. Please <strong>use comments for discussions</strong>  and <strong>please don't forget to vote :)</strong> for the answers that you liked (or perhaps did not like)! "
+
+#: forum/skins/default/templates/question.html:171
+msgid "please only give an answer, no discussions"
+msgstr "<span class='big strong'>Please try to give a substantial answer</span>. If you wanted to comment on the question or answer, just <strong>use the commenting tool</strong>. Please remember that you can always <strong>revise your answers</strong> - no need to answer the same question twice. Also, please <strong>don't forget to vote</strong> - it really helps to select the best questions and answers!"
+
+#: forum/skins/default/templates/question.html:207
+msgid "Login/Signup to Post Your Answer"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:210
+msgid "Answer Your Own Question"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:212
+msgid "Answer the question"
+msgstr "Post Your Answer"
+
+#: forum/skins/default/templates/question.html:229
+msgid "Question tags"
+msgstr "Tags"
+
+#: forum/skins/default/templates/question.html:239
+msgid "question asked"
+msgstr "Asked"
+
+#: forum/skins/default/templates/question.html:242
+msgid "question was seen"
+msgstr "Seen"
+
+#: forum/skins/default/templates/question.html:242
+msgid "times"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:245
+msgid "last updated"
+msgstr "Last updated"
+
+#: forum/skins/default/templates/question.html:250
+msgid "Related questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_edit.html:5
+#: forum/skins/default/templates/question_edit.html:63
+msgid "Edit question"
+msgstr ""
+
+#: forum/skins/default/templates/question_edit_tips.html:4
+msgid "question tips"
+msgstr "Tips"
+
+#: forum/skins/default/templates/question_edit_tips.html:9
+#, fuzzy, python-format
+msgid ""
+"\n"
+"                ask a question relevant to the %(app_title)s community \n"
+"                "
+msgstr ""
+"\n"
+"(one comment)"
+
+#: forum/skins/default/templates/question_edit_tips.html:15
+msgid "please try provide enough details"
+msgstr "provide enough details"
+
+#: forum/skins/default/templates/question_retag.html:5
+#: forum/skins/default/templates/question_retag.html:56
+msgid "Change tags"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:44
+msgid "up to 5 tags, less than 20 characters each"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:86
+msgid "Why use and modify tags?"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:89
+msgid "tags help us keep Questions organized"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:97
+msgid "tag editors receive special awards from the community"
+msgstr ""
+
+#: forum/skins/default/templates/questions.html:7
+msgid "Questions"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:6
+#: forum/skins/default/templates/reopen.html:16
+msgid "Reopen question"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:19
+msgid "Open the previously closed question"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:22
+msgid "The question was closed for the following reason "
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:22
+msgid "reason - leave blank in english"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:22
+msgid "on "
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:22
+msgid "date closed"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:29
+msgid "Reopen this question"
+msgstr ""
+
+#: forum/skins/default/templates/revisions_answer.html:7
+#: forum/skins/default/templates/revisions_answer.html:36
+#: forum/skins/default/templates/revisions_question.html:7
+#: forum/skins/default/templates/revisions_question.html:35
+msgid "Revision history"
+msgstr ""
+
+#: forum/skins/default/templates/revisions_answer.html:48
+#: forum/skins/default/templates/revisions_question.html:47
+msgid "click to hide/show revision"
+msgstr ""
+
+#: forum/skins/default/templates/revisions_answer.html:56
+#: forum/templatetags/node_tags.py:62
+msgid "edit"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:3
+msgid "Subscription"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:8
+msgid "You were automatically subscribed to this question."
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:10
+msgid "You are subscribed to this question."
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:13
+msgid "You are not subscribed to this question."
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:18
+#: forum/views/commands.py:323
+msgid "unsubscribe me"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:20
+#: forum/views/commands.py:323
+msgid "subscribe me"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:24
+#, python-format
+msgid ""
+"\n"
+"            (you can adjust your notification settings on your <a href=\"%(profile_url)s?sort=email_subscriptions\">profile</a>)\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:29
+#, fuzzy
+msgid "Once you sign in you will be able to subscribe for any updates here"
+msgstr "<span class='strong'>Here</span> (once you log in) you will be able to sign up for the periodic email updates about this question."
+
+#: forum/skins/default/templates/tag_selector.html:4
+#: forum/skins/default/templates/question_list/tag_selector.html:6
+msgid "Interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:10
+#: forum/skins/default/templates/tag_selector.html:27
+#: forum/skins/default/templates/question_list/related_tags.html:9
+#: forum/skins/default/templates/question_list/tag_selector.html:12
+#: forum/skins/default/templates/question_list/tag_selector.html:29
+#, python-format
+msgid "see questions tagged '%(tag_name)s'"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:14
+#: forum/skins/default/templates/question_list/tag_selector.html:16
+#, python-format
+msgid "remove '%(tag_name)s' from the list of interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:20
+#: forum/skins/default/templates/tag_selector.html:37
+#: forum/skins/default/templates/question_list/tag_selector.html:22
+#: forum/skins/default/templates/question_list/tag_selector.html:39
+msgid "Add"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:21
+#: forum/skins/default/templates/question_list/tag_selector.html:23
+msgid "Ignored tags"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:31
+#: forum/skins/default/templates/question_list/tag_selector.html:33
+#, python-format
+msgid "remove '%(tag_name)s' from the list of ignored tags"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:40
+#: forum/skins/default/templates/question_list/tag_selector.html:42
+msgid "keep ignored questions hidden"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:6
+#: forum/skins/default/templates/tags.html:30
+msgid "Tag list"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:32
+msgid "sorted alphabetically"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:32
+msgid "by name"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:33
+msgid "sorted by frequency of tag use"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:33
+msgid "by popularity"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:39
+msgid "All tags matching query"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:39
+msgid "all tags - make this empty in english"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:42
+msgid "Nothing found"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:5
+#: forum/skins/default/templates/auth/auth_settings.html:7
+msgid "Authentication settings"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:9
+msgid "These are the external authentication providers currently associated with your account."
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:12
+msgid "remove"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:17
+msgid "You currently have no external authentication provider associated with your account."
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:19
+msgid "Add new provider"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:21
+msgid "This is where you can change your password. Make sure you remember it!"
+msgstr "<span class='strong'>To change your password</span> please fill out and submit this form"
+
+#: forum/skins/default/templates/auth/auth_settings.html:24
+msgid "You can set up a password for your account, so you can login using standard username and password!"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:31
+#, fuzzy
+msgid "Create password"
+msgstr "Password <i>(please retype)</i>"
+
+#: forum/skins/default/templates/auth/complete.html:5
+msgid "Connect your OpenID with this site"
+msgstr "New user signup"
+
+#: forum/skins/default/templates/auth/complete.html:8
+msgid "Connect your OpenID with your account on this site"
+msgstr "New user signup"
+
+#: forum/skins/default/templates/auth/complete.html:12
+msgid "You are here for the first time with "
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:13
+msgid "Please create your screen name and save your email address. Saved email address will let you subscribe for the updates on the most interesting questions and will be used to create and retrieve your unique avatar image. "
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:15
+msgid "This account already exists, please use another."
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:30
+msgid "Sorry, looks like we have some errors:"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:47
+msgid "Screen name label"
+msgstr "<strong>Screen Name</strong> (<i>will be shown to others</i>)"
+
+#: forum/skins/default/templates/auth/complete.html:54
+msgid "Email address label"
+msgstr "<strong>Email Address</strong> (<i>will <strong>not</strong> be shared with anyone, must be valid</i>)"
+
+#: forum/skins/default/templates/auth/complete.html:60
+#: forum/skins/default/templates/auth/signup.html:18
+msgid "receive updates motivational blurb"
+msgstr "<strong>Receive forum updates by email</strong> - this will help our community grow and become more useful.<br/>By default <span class='orange'>Q&amp;A</span> forum sends up to <strong>one email digest per week</strong>  - only when there is anything new.<br/>If you like, please adjust this now or any time later from your user account."
+
+#: forum/skins/default/templates/auth/complete.html:64
+#: forum/skins/default/templates/auth/signup.html:22
+msgid "please select one of the options above"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:67
+msgid "Tag filter tool will be your right panel, once you log in."
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:68
+msgid "create account"
+msgstr "Signup"
+
+#: forum/skins/default/templates/auth/complete.html:77
+msgid "Existing account"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:78
+msgid "user name"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:79
+msgid "password"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:86
+msgid "Register"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:87
+msgid "Forgot your password?"
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:6
+#: forum/skins/default/templates/auth/temp_login_email.html:6
+msgid "Greetings from the Q&A forum"
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:8
+msgid "To make use of the Forum, please follow the link below:"
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:12
+msgid "Following the link above will help us verify your email address."
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:14
+#: forum/skins/default/templates/auth/temp_login_email.html:14
+msgid ""
+"If you beleive that this message was sent in mistake -\n"
+"    no further action is needed. Just ingore this email, we apologize\n"
+"    for any inconvenience"
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:18
+#: forum/skins/default/templates/auth/temp_login_email.html:18
+#: forum/skins/default/templates/notifications/answeraccepted.html:15
+#: forum/skins/default/templates/notifications/newanswer.html:25
+#: forum/skins/default/templates/notifications/newcomment.html:32
+#: forum/skins/default/templates/notifications/newmember.html:15
+#: forum/skins/default/templates/notifications/newquestion.html:25
+#, fuzzy
+msgid ""
+"Sincerely,<br />\n"
+"    Forum Administrator"
+msgstr ""
+"Sincerely,\n"
+"Q&A Forum Administrator"
+
+#: forum/skins/default/templates/auth/signin.html:6
+msgid "Login"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:24
+msgid "User login"
+msgstr "User login"
+
+#: forum/skins/default/templates/auth/signin.html:36
+#: forum/skins/default/templates/auth/signin.html:86
+#: forum/skins/default/templates/auth/signin.html:92
+msgid "Or..."
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:39
+msgid "Click to sign in through any of these services."
+msgstr "<p><span class=\"big strong\">Please select your favorite login method below.</span></p><p><font color=\"gray\">External login services use <a href=\"http://openid.net\"><b>OpenID</b></a> technology, where your password always stays confidential between you and your login provider and you don't have to remember another one. CNPROG option requires your login name and password entered here.</font></p>"
+
+#: forum/skins/default/templates/auth/signin.html:44
+msgid "Validate my email after I login."
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:94
+msgid "Click"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:94
+msgid "if you're having troubles signing in."
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:98
+msgid "Enter your "
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:154
+msgid "Why use OpenID?"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:157
+msgid "with openid it is easier"
+msgstr "With the OpenID you don't need to create new username and password."
+
+#: forum/skins/default/templates/auth/signin.html:160
+msgid "reuse openid"
+msgstr "You can safely re-use the same login for all OpenID-enabled websites."
+
+#: forum/skins/default/templates/auth/signin.html:163
+msgid "openid is widely adopted"
+msgstr "There are > 160,000,000 OpenID account in use. Over 10,000 sites are OpenID-enabled."
+
+#: forum/skins/default/templates/auth/signin.html:166
+msgid "openid is supported open standard"
+msgstr "OpenID is based on an open standard, supported by many organizations."
+
+#: forum/skins/default/templates/auth/signin.html:171
+msgid "Find out more"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:172
+msgid "Get OpenID"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:4
+msgid "Signup"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:8
+msgid "Create login name and password"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:10
+msgid "Traditional signup info"
+msgstr "<span class='strong big'>If you prefer, create your forum login name and password here. However</span>, please keep in mind that we also support <strong>OpenID</strong> login method. With <strong>OpenID</strong> you can simply reuse your external login (e.g. Gmail or AOL) without ever sharing your login details with anyone and having to remember yet another password."
+
+#: forum/skins/default/templates/auth/signup.html:31
+msgid "Create Account"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:32
+msgid "or"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:33
+msgid "return to login page"
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_email.html:8
+msgid "You're seeing this because someone requested a temporary login link"
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_email.html:12
+msgid "Following the link above will give you access to your account."
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:5
+msgid "Request temporary login key"
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:7
+msgid "Account: request temporary login key"
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:8
+msgid ""
+"\n"
+"    If you're experiencing problems accessing your account, or if you forgot your password,\n"
+"    here you can request a temporary login key. Fill out your account email and we'll send you a temporary access link that\n"
+"    will enable you to access your account. This token is valid only once and for a limited period of time.\n"
+" "
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:25
+#, fuzzy
+msgid "Send link"
+msgstr "link"
+
+#: forum/skins/default/templates/node/accept_button.html:5
+#, python-format
+msgid "%(who)s has selected this answer as the correct answer"
+msgstr ""
+
+#: forum/skins/default/templates/node/accept_button.html:5
+msgid "mark this answer as the accepted answer"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:22
+msgid "I like this comment (click again to cancel)"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:26
+#, fuzzy
+msgid "Edit comment"
+msgstr "post a comment"
+
+#: forum/skins/default/templates/node/comments.html:30
+#, fuzzy
+msgid "Delete comment"
+msgstr "post a comment"
+
+#: forum/skins/default/templates/node/comments.html:42
+#, python-format
+msgid "showing %(showing)s of %(total)s"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:44
+msgid "show all"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:47
+#, fuzzy
+msgid "add new comment"
+msgstr "post a comment"
+
+#: forum/skins/default/templates/node/comments.html:55
+#, fuzzy
+msgid " add comment"
+msgstr "post a comment"
+
+#: forum/skins/default/templates/node/comments.html:58
+#, python-format
+msgid ""
+"\n"
+"                have <span class=\"comments-char-left-count\">%(max_length)s</span> characters left\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:71
+#, fuzzy
+msgid "just now"
+msgstr "Logout Now"
+
+#: forum/skins/default/templates/node/favorite_mark.html:3
+msgid "mark/unmark this question as favorite (click again to cancel)"
+msgstr ""
+
+#: forum/skins/default/templates/node/vote_buttons.html:3
+msgid "I like this post (click again to cancel)"
+msgstr ""
+
+#: forum/skins/default/templates/node/vote_buttons.html:7
+msgid "current number of votes"
+msgstr ""
+
+#: forum/skins/default/templates/node/vote_buttons.html:10
+msgid "I dont like this post (click again to cancel)"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/answeraccepted.html:6
+#: forum/skins/default/templates/notifications/digest.html:7
+#: forum/skins/default/templates/notifications/newanswer.html:6
+#: forum/skins/default/templates/notifications/newcomment.html:6
+#: forum/skins/default/templates/notifications/newmember.html:6
+#: forum/skins/default/templates/notifications/newquestion.html:6
+msgid "Hello"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/answeraccepted.html:9
+#, python-format
+msgid ""
+"\n"
+"        Just to let you know that %(accepter)s has just accepted %(answer_author)s's answer on his question\n"
+"        <a href=\"%(app_url)s%(question_url)s\">%(question_title)s</a>:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:9
+#, python-format
+msgid ""
+"\n"
+"    This is the %(digest_type)s activity digest for %(app_title)s\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:15
+#, python-format
+msgid ""
+"\n"
+"            %(nusers_count)s new user%(nusers_count_pluralize)s joined the %(app_title)s community:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:28
+#, python-format
+msgid ""
+"\n"
+"            %(question_count)s of your subscriptions have updates:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:35
+#, fuzzy
+msgid "On question "
+msgstr "Tips"
+
+#: forum/skins/default/templates/notifications/digest.html:37
+#, fuzzy, python-format
+msgid ""
+"\n"
+"                    %(answer_count)s new answer%(answer_count_pluralize)s\n"
+"                "
+msgstr ""
+"\n"
+"(one comment)"
+
+#: forum/skins/default/templates/notifications/digest.html:42
+#, fuzzy, python-format
+msgid ""
+"\n"
+"                    %(comment_count)s new comment%(comment_count_pluralize)s\n"
+"                "
+msgstr ""
+"\n"
+"(one comment)"
+
+#: forum/skins/default/templates/notifications/digest.html:46
+msgid "on your own post(s)"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:50
+#, fuzzy
+msgid "an answer was accepted"
+msgstr "answer accepted"
+
+#: forum/skins/default/templates/notifications/digest.html:59
+#, python-format
+msgid ""
+"\n"
+"            %(question_count)s new question%(question_count_pluralize)s\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:63
+msgid "matching your interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:65
+msgid "posted :"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:71
+#, fuzzy, python-format
+msgid ""
+"\n"
+"                    Posted by %(author_name)s in %(question_time)s\n"
+"                "
+msgstr ""
+"\n"
+"<div class=\"questions-count\">%(q_num)s</div><p>question</p>"
+
+#: forum/skins/default/templates/notifications/feedback.html:7
+#, python-format
+msgid ""
+"\n"
+"    Hello, this is a %(site_title)s forum feedback message\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:13
+msgid "Sender"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:15
+#: forum/skins/default/templates/notifications/feedback.html:18
+#: forum/skins/default/templates/users/info.html:93
+msgid "email"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:17
+msgid "anonymous"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:25
+msgid "Message body:"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newanswer.html:9
+#, python-format
+msgid ""
+"\n"
+"        %(author_name)s has just posted a new answer on %(app_title)s to the question\n"
+"        <a href=\"%(app_url)s%(question_url)s\">%(question_title)s\"</a>:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newanswer.html:20
+#: forum/skins/default/templates/notifications/newcomment.html:28
+#: forum/skins/default/templates/notifications/newquestion.html:20
+msgid ""
+"\n"
+"        Don't forget to come over and cast your vote.\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newcomment.html:9
+#, fuzzy, python-format
+msgid ""
+"\n"
+"            %(author_name)s has just posted a comment on\n"
+"        "
+msgstr ""
+"\n"
+"<div class=\"questions-count\">%(q_num)s</div><p>question tagged</p><p><span class=\"tag\">%(tagname)s</span></p>"
+
+#: forum/skins/default/templates/notifications/newcomment.html:14
+#, python-format
+msgid ""
+"\n"
+"                the answer posted by <a href=\"%(app_url)s%(poster_url)s\">%(poster_name)s</a> to\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newcomment.html:19
+#, python-format
+msgid ""
+"\n"
+"             the question  <a href=\"%(app_url)s%(question_url)s\">%(question_title)s</a>\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newmember.html:9
+#, python-format
+msgid ""
+"\n"
+"        %(newmember_name)s has just joined %(app_title)s. You can visit %(newmember_name)s's profile using the following link: <br />\n"
+"        <a href=\"%(app_url)s%(newmember_url)s\">%(newmember_name)s profile</a>\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newquestion.html:9
+#, python-format
+msgid ""
+"\n"
+"        %(author_name)s has just posted a new question on %(app_title)s, with title\n"
+"        <a href=\"%(app_url)s%(question_url)s\">%(question_title)s</a> and tagged <em>%(question_tags)s</em>:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/base.html:13
+msgid "OSQA administration area"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/base.html:26
+msgid "Administration menu"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:7
+msgid "Dashboard"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:10
+msgid "Welcome to the OSQA administration area."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:17
+msgid "Site statistics"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:21
+#: forum/skins/default/templates/osqaadmin/index.html:26
+msgid "in the last 24 hours"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:31
+msgid "user"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:31
+msgid "joined in the last 24 hours"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:37
+msgid "Site status"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:42
+msgid "Your site is running in bootstrap mode, click the button bellow to revert to defaults."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:45
+msgid "Your site is running in standard mode, click the button bellow to run in bootstrap mode."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:47
+msgid "Your site is running with some customized settings, click the buttons bellow to run with defaults or in bootstrap mode"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:51
+msgid "Are you sure you want to revert to the defaults?"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:51
+msgid "revert to defaults"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:54
+msgid "Are you sure you want to run bootstrap mode?"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:54
+msgid "go bootstrap"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:59
+msgid "Recalculate scores and reputation"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:60
+msgid "This is a heavy operation, are you sure?"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:60
+msgid "Recalculate"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:65
+msgid "Recent activity"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/item.html:12
+msgid "this question has an accepted answer"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/related_tags.html:6
+msgid "Related tags"
+msgstr "Tags"
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:4
+msgid "most recently updated questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:4
+msgid "active"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:5
+msgid "most recently asked questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:5
+msgid "newest"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:6
+msgid "hottest questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:6
+msgid "hottest"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:7
+msgid "most voted questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:7
+msgid "most voted"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:5
+msgid "Found by tags"
+msgstr "Tagged questions"
+
+#: forum/skins/default/templates/question_list/title.html:9
+msgid "Search results"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:11
+msgid "Found by title"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:15
+msgid "Unanswered questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:17
+#: forum/skins/default/templates/users/subscriptions.html:74
+msgid "All questions"
+msgstr ""
+
+#: forum/skins/default/templates/sidebar/recent_awards.html:4
+msgid "Recent awards"
+msgstr "Recent badges"
+
+#: forum/skins/default/templates/sidebar/recent_awards.html:15
+msgid "all awards"
+msgstr "all badges"
+
+#: forum/skins/default/templates/sidebar/recent_tags.html:4
+msgid "Recent tags"
+msgstr ""
+
+#: forum/skins/default/templates/sidebar/recent_tags.html:12
+msgid "popular tags"
+msgstr "tags"
+
+#: forum/skins/default/templates/users/edit.html:6
+msgid "Edit user profile"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:19
+msgid "edit profile"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:31
+msgid "image associated with your email address"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:31
+#, python-format
+msgid "avatar, see %(gravatar_faq_url)s"
+msgstr "<a href='%(gravatar_faq_url)s'>gravatar</a>"
+
+#: forum/skins/default/templates/users/edit.html:36
+#: forum/skins/default/templates/users/info.html:52
+msgid "Registered user"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:43
+msgid "Screen Name"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:86
+#: forum/skins/default/templates/users/subscriptions.html:116
+msgid "Update"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:22
+#: forum/skins/default/templates/users/signature.html:6
+#: forum/skins/default/templates/users/users.html:26
+msgid "reputation"
+msgstr "karma"
+
+#: forum/skins/default/templates/users/info.html:32
+msgid "Moderate this user"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:44
+msgid "update profile"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:56
+msgid "real name"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:61
+msgid "member for"
+msgstr "member since"
+
+#: forum/skins/default/templates/users/info.html:66
+msgid "last seen"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:72
+msgid "user website"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:78
+msgid "location"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:86
+msgid "age"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:87
+msgid "age unit"
+msgstr "years old"
+
+#: forum/skins/default/templates/users/info.html:100
+msgid "todays unused votes"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:101
+msgid "votes left"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:13
+#, python-format
+msgid ""
+"\n"
+"                <span class=\"count\">1</span> Question\n"
+"                "
+msgid_plural ""
+"\n"
+"                <span class=\"count\">%(counter)s</span> Questions\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:29
+#, python-format
+msgid ""
+"\n"
+"                <span class=\"count\">1</span> Answer\n"
+"                "
+msgid_plural ""
+"\n"
+"                <span class=\"count\">%(counter)s</span> Answers\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:42
+#, python-format
+msgid "the answer has been voted for %(vote_count)s times"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:42
+msgid "this answer has been selected as correct"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:58
+#, python-format
+msgid ""
+"\n"
+"                    <span class=\"count\">1</span> Vote\n"
+"                "
+msgid_plural ""
+"\n"
+"                    <span class=\"count\">%(cnt)s</span> Votes\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:69
+msgid "thumb up"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:70
+msgid "user has voted up this many times"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:74
+msgid "thumb down"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:75
+msgid "user voted down this many times"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:84
+#, python-format
+msgid ""
+"\n"
+"                    <span class=\"count\">1</span> Tag\n"
+"                "
+msgid_plural ""
+"\n"
+"                    <span class=\"count\">%(counter)s</span> Tags\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:97
+#, python-format
+msgid "see other questions with %(view_user)s's contributions tagged '%(tag_name)s' "
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:112
+#, python-format
+msgid ""
+"\n"
+"            <span class=\"count\">1</span> Badge\n"
+"            "
+msgid_plural ""
+"\n"
+"            <span class=\"count\">%(counter)s</span> Badges\n"
+"            "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/subscriptions.html:8
+#, fuzzy
+msgid "Notifications and subscription settings"
+msgstr "<span class='big strong'>Adjust frequency of email updates.</span> Receive updates on interesting questions by email, <strong><br/>help the community</strong> by answering questions of your colleagues. If you do not wish to receive emails - select 'no email' on all items below.<br/>Updates are only sent when there is any new activity on selected items."
+
+#: forum/skins/default/templates/users/subscriptions.html:10
+msgid ""
+"\n"
+"        Here you can decide which types of notifications you wish to receive, and it's frequency.<br />\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:14
+msgid ""
+"\n"
+"        Currently you have notifications enabled. You can always stop all notifications without loosing your settings and restart them afterwards.<br />\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:18
+msgid ""
+"\n"
+"        Currently you have notifications disabled. You can enable them clicking on the <strong>Start notifications</strong> button bellow.<br />\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:28
+msgid "Notify me when:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:32
+msgid "A new member joins"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:36
+#, fuzzy
+msgid "A new question is posted"
+msgstr "Tips"
+
+#: forum/skins/default/templates/users/subscriptions.html:40
+msgid "A new question matching my interesting tags is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:44
+msgid "There's an update on one of my subscriptions"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:52
+msgid "Auto subscribe me to:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:57
+#, fuzzy
+msgid "Questions I ask"
+msgstr "Tags"
+
+#: forum/skins/default/templates/users/subscriptions.html:60
+#, fuzzy
+msgid "Questions I answer"
+msgstr "answer"
+
+#: forum/skins/default/templates/users/subscriptions.html:63
+#, fuzzy
+msgid "Questions I comment"
+msgstr "question comment"
+
+#: forum/skins/default/templates/users/subscriptions.html:68
+#, fuzzy
+msgid "Questions I view"
+msgstr "Tags"
+
+#: forum/skins/default/templates/users/subscriptions.html:71
+msgid "All questions matching my interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:82
+msgid "On my subscriptions, notify me when:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:87
+#, fuzzy
+msgid "An answer is posted"
+msgstr "Tips"
+
+#: forum/skins/default/templates/users/subscriptions.html:90
+msgid "A comment on one of my posts is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:95
+msgid "A comment is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:98
+#, fuzzy
+msgid "An answer is accepted"
+msgstr "answer accepted"
+
+#: forum/skins/default/templates/users/subscriptions.html:106
+msgid "More:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:111
+msgid "Notify me when someone replys to one of my comments on any post using the <pre>@username</pre> notation"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:118
+msgid "Stop notifications"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:120
+msgid "Start notifications"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:7
+msgid "User profile"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:7
+msgid "overview"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:9
+msgid "recent activity"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:11
+msgid "graph of user reputation"
+msgstr "Graph of user karma"
+
+#: forum/skins/default/templates/users/tabs.html:12
+msgid "reputation history"
+msgstr "karma history"
+
+#: forum/skins/default/templates/users/tabs.html:15 forum/views/users.py:196
+msgid "user vote record"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:15
+msgid "casted votes"
+msgstr "votes"
+
+#: forum/skins/default/templates/users/tabs.html:18
+msgid "questions that user selected as his/her favorite"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:19
+msgid "favorites"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:22
+msgid "email subscription settings"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:23
+msgid "subscriptions"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:6
+#: forum/skins/default/templates/users/users.html:24
+msgid "Users"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:27
+msgid "recent"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:28
+msgid "oldest"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:29
+msgid "by username"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:35
+#, python-format
+msgid "users matching query %(suser)s:"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:39
+msgid "Nothing found."
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:168 forum/templatetags/extra_tags.py:195
+msgid "reputation points"
+msgstr "karma"
+
+#: forum/templatetags/extra_tags.py:248
+msgid "2 days ago"
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:250
+msgid "yesterday"
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:252
+#, python-format
+msgid "%(hr)d hour ago"
+msgid_plural "%(hr)d hours ago"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/templatetags/extra_tags.py:254
+#, python-format
+msgid "%(min)d min ago"
+msgid_plural "%(min)d mins ago"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/templatetags/node_tags.py:58
+msgid "permanent link"
+msgstr "link"
+
+#: forum/templatetags/node_tags.py:58
+msgid "answer permanent link"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:64
+msgid "retag"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:68
+msgid "reopen"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:70
+msgid "close"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:73 forum/views/commands.py:124
+#: forum/views/commands.py:136
+msgid "flag"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:79
+msgid "report as offensive (i.e containing spam, advertising, malicious text, etc.)"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:82
+msgid "delete"
+msgstr ""
+
+#: forum/templatetags/question_list_tags.py:57
+#, fuzzy
+msgid "<strong>Newest</strong> questions are shown first. "
+msgstr " "
+
+#: forum/templatetags/question_list_tags.py:58
+msgid "Questions are sorted by the <strong>time of last update</strong>."
+msgstr ""
+
+#: forum/templatetags/question_list_tags.py:59
+msgid "Questions sorted by <strong>number of responses</strong>."
+msgstr "Questions sorted by the <strong>number of answers</strong>."
+
+#: forum/templatetags/question_list_tags.py:60
+msgid "Questions are sorted by the <strong>number of votes</strong>."
+msgstr ""
+
+#: forum/templatetags/user_tags.py:58 forum/views/readers.py:293
+#, python-format
+msgid "Revision n. %(rev_number)d"
+msgstr ""
+
+#: forum/utils/forms.py:32
+msgid "this field is required"
+msgstr ""
+
+#: forum/utils/forms.py:47
+msgid "choose a username"
+msgstr "Choose screen name"
+
+#: forum/utils/forms.py:52
+msgid "user name is required"
+msgstr ""
+
+#: forum/utils/forms.py:53
+msgid "sorry, this name is taken, please choose another"
+msgstr ""
+
+#: forum/utils/forms.py:54
+msgid "sorry, this name is not allowed, please choose another"
+msgstr ""
+
+#: forum/utils/forms.py:55
+msgid "sorry, there is no user with this name"
+msgstr ""
+
+#: forum/utils/forms.py:56
+msgid "sorry, we have a serious error - user name is taken by several users"
+msgstr ""
+
+#: forum/utils/forms.py:57
+msgid "user name can only consist of letters, empty space and underscore"
+msgstr ""
+
+#: forum/utils/forms.py:105
+msgid "your email address"
+msgstr "Your email <i>(never shared)</i>"
+
+#: forum/utils/forms.py:106
+msgid "email address is required"
+msgstr ""
+
+#: forum/utils/forms.py:108
+msgid "this email is already used by someone else, please choose another"
+msgstr ""
+
+#: forum/utils/forms.py:133
+msgid "choose password"
+msgstr "Password"
+
+#: forum/utils/forms.py:134
+msgid "password is required"
+msgstr ""
+
+#: forum/utils/forms.py:137
+msgid "retype password"
+msgstr "Password <i>(please retype)</i>"
+
+#: forum/utils/forms.py:138
+msgid "please, retype your password"
+msgstr ""
+
+#: forum/utils/forms.py:139
+msgid "sorry, entered passwords did not match, please try again"
+msgstr ""
+
+#: forum/views/admin.py:47
+#, python-format
+msgid "'%s' settings saved succesfully"
+msgstr ""
+
+#: forum/views/admin.py:141
+msgid "Bootstrap mode enabled"
+msgstr ""
+
+#: forum/views/admin.py:155
+msgid "All values reverted to defaults"
+msgstr ""
+
+#: forum/views/admin.py:171
+msgid "All values recalculated"
+msgstr ""
+
+#: forum/views/auth.py:103 forum/views/auth.py:112
+msgid "Sorry, these login credentials belong to anoother user. Plese terminate your current session and try again."
+msgstr ""
+
+#: forum/views/auth.py:105
+msgid "You are already logged in with that user."
+msgstr ""
+
+#: forum/views/auth.py:110
+msgid "These login credentials are already associated with your account."
+msgstr ""
+
+#: forum/views/auth.py:116
+msgid "The new credentials are now associated with your account"
+msgstr ""
+
+#: forum/views/auth.py:157
+msgid "Oops, something went wrong in the middle of this process. Please try again."
+msgstr ""
+
+#: forum/views/auth.py:219
+msgid "Temporary login link"
+msgstr ""
+
+#: forum/views/auth.py:224
+msgid "An email has been sent with your temporary login key"
+msgstr ""
+
+#: forum/views/auth.py:239
+msgid "You are logged in with a temporary access key, please take the time to fix your issue with authentication."
+msgstr ""
+
+#: forum/views/auth.py:245
+msgid "Email Validation"
+msgstr ""
+
+#: forum/views/auth.py:256
+msgid "Thank you, your email is now validated."
+msgstr ""
+
+#: forum/views/auth.py:280
+msgid "Your password was changed"
+msgstr ""
+
+#: forum/views/auth.py:282
+#, fuzzy
+msgid "New password set"
+msgstr "Recover password"
+
+#: forum/views/auth.py:315
+#, python-format
+msgid "You removed the association with %s"
+msgstr ""
+
+#: forum/views/auth.py:353
+#, python-format
+msgid "Welcome back %s, you are now logged in"
+msgstr ""
+
+#: forum/views/commands.py:20
+#, python-format
+msgid ""
+"\n"
+"            Sorry, but you don't have enough reputation points to %(action)s.<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:29
+#, python-format
+msgid ""
+"\n"
+"            Sorry but you cannot %(action)s your own post.<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:38
+#, python-format
+msgid ""
+"\n"
+"            Sorry but anonymous users cannot %(action)s.<br />\n"
+"            Please login or create an account <a href'%(signin_url)s'>here</a>.\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:47
+#, python-format
+msgid ""
+"\n"
+"            Sorry, but you don't have enough %(action)s left for today..<br />\n"
+"            The limit is %(limit)s per day..<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:57
+#, python-format
+msgid ""
+"\n"
+"            Sorry, but you cannot %(action)s twice the same post.<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:71 forum/views/commands.py:74
+#: forum/views/commands.py:111
+msgid "vote"
+msgid_plural "votes"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/views/commands.py:89
+#, python-format
+msgid "Sorry but you cannot cancel a vote after %(ndays)d %(tdays)s from the original vote"
+msgstr ""
+
+#: forum/views/commands.py:90
+msgid "day"
+msgid_plural "days"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/views/commands.py:110
+#, python-format
+msgid "You have %(nvotes)s %(tvotes)s left today."
+msgstr ""
+
+#: forum/views/commands.py:121 forum/views/commands.py:127
+msgid "flag posts"
+msgstr ""
+
+#: forum/views/commands.py:132
+msgid "flags"
+msgstr ""
+
+#: forum/views/commands.py:149 forum/views/commands.py:155
+#, fuzzy
+msgid "like comments"
+msgstr "post a comment"
+
+#: forum/views/commands.py:152
+msgid "like"
+msgstr ""
+
+#: forum/views/commands.py:179 forum/views/commands.py:182
+#, fuzzy
+msgid "delete comments"
+msgstr "post a comment"
+
+#: forum/views/commands.py:197
+msgid "mark a question as favorite"
+msgstr ""
+
+#: forum/views/commands.py:221 forum/views/commands.py:233
+#, fuzzy
+msgid "comment"
+msgstr "post a comment"
+
+#: forum/views/commands.py:224 forum/views/commands.py:351
+msgid "Invalid request"
+msgstr ""
+
+#: forum/views/commands.py:230
+#, fuzzy
+msgid "edit comments"
+msgstr "post a comment"
+
+#: forum/views/commands.py:240
+msgid "Comment is empty"
+msgstr ""
+
+#: forum/views/commands.py:265
+#, fuzzy
+msgid "accept answers"
+msgstr "oldest"
+
+#: forum/views/commands.py:271
+msgid "Sorry but only the question author can accept an answer"
+msgstr ""
+
+#: forum/views/commands.py:295 forum/views/commands.py:298
+msgid "delete posts"
+msgstr ""
+
+#: forum/views/meta.py:43
+#, python-format
+msgid "Feedback message from %(site_name)s"
+msgstr ""
+
+#: forum/views/meta.py:46
+msgid "Thanks for the feedback!"
+msgstr ""
+
+#: forum/views/meta.py:53
+msgid "We look forward to hearing your feedback! Please, give it next time :)"
+msgstr ""
+
+#: forum/views/readers.py:64
+msgid "Open questions without an accepted answer"
+msgstr ""
+
+#: forum/views/readers.py:73
+#, python-format
+msgid "Questions tagged <span class=\"tag\">%(tag)s</span>"
+msgstr ""
+
+#: forum/views/readers.py:131
+#, python-format
+msgid "questions matching '%(keywords)s'"
+msgstr ""
+
+#: forum/views/users.py:152
+msgid "user profile"
+msgstr ""
+
+#: forum/views/users.py:152
+msgid "user profile overview"
+msgstr ""
+
+#: forum/views/users.py:186
+msgid "recent user activity"
+msgstr ""
+
+#: forum/views/users.py:186
+msgid "profile - recent activity"
+msgstr ""
+
+#: forum/views/users.py:196
+msgid "profile - votes"
+msgstr ""
+
+#: forum/views/users.py:203
+msgid "user reputation in the community"
+msgstr "user karma"
+
+#: forum/views/users.py:203
+msgid "profile - user reputation"
+msgstr "Profile - User's Karma"
+
+#: forum/views/users.py:214
+msgid "favorite questions"
+msgstr ""
+
+#: forum/views/users.py:214
+msgid "profile - favorite questions"
+msgstr ""
+
+#: forum/views/users.py:220
+#, fuzzy
+msgid "subscription settings"
+msgstr "<span class='big strong'>Adjust frequency of email updates.</span> Receive updates on interesting questions by email, <strong><br/>help the community</strong> by answering questions of your colleagues. If you do not wish to receive emails - select 'no email' on all items below.<br/>Updates are only sent when there is any new activity on selected items."
+
+#: forum/views/users.py:220
+#, fuzzy
+msgid "profile - subscriptions"
+msgstr "Profile - User's Karma"
+
+#: forum/views/users.py:230
+msgid "Notifications are now enabled"
+msgstr ""
+
+#: forum/views/users.py:232
+msgid "Notifications are now disabled"
+msgstr ""
+
+#: forum/views/users.py:239
+#, fuzzy
+msgid "New subscription settings are now saved"
+msgstr "<span class='big strong'>Adjust frequency of email updates.</span> Receive updates on interesting questions by email, <strong><br/>help the community</strong> by answering questions of your colleagues. If you do not wish to receive emails - select 'no email' on all items below.<br/>Updates are only sent when there is any new activity on selected items."
+
+#: forum/views/writers.py:68
+msgid "uploading images is limited to users with >60 reputation points"
+msgstr "sorry, file uploading requires karma >60"
+
+#: forum/views/writers.py:70
+msgid "allowed file types are 'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'"
+msgstr ""
+
+#: forum/views/writers.py:72
+#, python-format
+msgid "maximum upload file size is %sM"
+msgstr ""
+
+#: forum/views/writers.py:74
+#, python-format
+msgid "Error uploading file. Please contact the site administrator. Thank you. %s"
+msgstr ""
+
+#: forum/views/writers.py:85
+msgid "Initial revision"
+msgstr ""
+
+#: forum/views/writers.py:143
+msgid "Retag"
+msgstr ""
+
+#: forum_modules/books/urls.py:7 forum_modules/books/urls.py:8
+#: forum_modules/books/urls.py:9
+msgid "books/"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:17
+#: forum_modules/default_badges/badges.py:24
+#: forum_modules/default_badges/badges.py:31
+#, python-format
+msgid "Asked a question with %s views"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:39
+#: forum_modules/default_badges/badges.py:53
+#: forum_modules/default_badges/badges.py:67
+#, fuzzy, python-format
+msgid "Answer voted up %s times"
+msgstr "Post Your Answer"
+
+#: forum_modules/default_badges/badges.py:46
+#: forum_modules/default_badges/badges.py:60
+#: forum_modules/default_badges/badges.py:74
+#, python-format
+msgid "Question voted up %s times"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:82
+#: forum_modules/default_badges/badges.py:89
+#, python-format
+msgid "Question favorited by %s users"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:97
+#, python-format
+msgid "Deleted own post with score of %s or higher"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:108
+#, python-format
+msgid "Deleted own post with score of %s or lower"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:120
+msgid "First flagged post"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:127
+msgid "First down vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:134
+msgid "First retag"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:141
+msgid "First up vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:148
+msgid "First edit"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:155
+msgid "First accepted answer on your own question"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:162
+msgid "Completed all user profile fields"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:169
+msgid "First rollback"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:177
+#, python-format
+msgid "Voted %s times"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:184
+#, python-format
+msgid "Left %s comments"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:192
+#, fuzzy, python-format
+msgid "Answered your own question with at least %s up votes"
+msgstr "<span class='big strong'>You are welcome to answer your own question</span>, but please make sure to give an <strong>answer</strong>. Remember that you can always <strong>revise your original question</strong>. Please <strong>use comments for discussions</strong>  and <strong>please don't forget to vote :)</strong> for the answers that you liked (or perhaps did not like)! "
+
+#: forum_modules/default_badges/badges.py:205
+msgid "Strunk & White"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:206
+#, python-format
+msgid "Edited %s entries"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:217
+msgid "Asked first question with at least one up vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:228
+msgid "Answered first question with at least one up vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:260
+#, python-format
+msgid "First answer was accepted with at least %s up votes"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:271
+#, python-format
+msgid "Accepted answer and voted up %s times"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:282
+#, python-format
+msgid "Answered a question more than %(dif_days)s days later with at least %(up_votes)s votes"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:295
+#, python-format
+msgid "Created a tag used by %s questions"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:6
+msgid "Popular Question views"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:7
+msgid ""
+"\n"
+"Number of question views required to award a Popular Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:12
+msgid "Notable Question views"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:13
+msgid ""
+"\n"
+"Number of question views required to award a Notable Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:18
+msgid "Famous Question views"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:19
+msgid ""
+"\n"
+"Number of question views required to award a Famous Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:24
+msgid "Nice Answer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:25
+msgid ""
+"\n"
+"Number of up votes required to award a Nice Answer badge to the answer author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:30
+#, fuzzy
+msgid "Nice Question up votes"
+msgstr "Tags"
+
+#: forum_modules/default_badges/settings.py:31
+msgid ""
+"\n"
+"Number of up votes required to award a Nice Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:36
+msgid "Good Answer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:37
+msgid ""
+"\n"
+"Number of up votes required to award a Good Answer badge to the answer author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:42
+#, fuzzy
+msgid "Good Question up votes"
+msgstr "Tags"
+
+#: forum_modules/default_badges/settings.py:43
+msgid ""
+"\n"
+"Number of up votes required to award a Good Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:48
+msgid "Great Answer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:49
+msgid ""
+"\n"
+"Number of up votes required to award a Great Answer badge to the answer author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:54
+#, fuzzy
+msgid "Great Question up votes"
+msgstr "Tags"
+
+#: forum_modules/default_badges/settings.py:55
+msgid ""
+"\n"
+"Number of up votes required to award a Great Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:60
+msgid "Favorite Question favorite count"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:61
+msgid ""
+"\n"
+"How many times a question needs to be favorited by other users to award a Favorite Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:66
+msgid "Stellar Question favorite count"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:67
+msgid ""
+"\n"
+"How many times a question needs to be favorited by other users to award a Stellar Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:72
+msgid "Disciplined minimum score"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:73
+msgid ""
+"\n"
+"Minimum score a question needs to have to award the Disciplined badge to an author of a question who deletes it.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:78
+msgid "Peer Pressure maximum score"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:79
+msgid ""
+"\n"
+"Maximum score a question needs to have to award the Peer Pressure badge to an author of a question who deletes it.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:84
+msgid "Civic Duty votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:85
+msgid ""
+"\n"
+"Number of votes an user needs to cast to be awarded the Civic Duty badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:90
+msgid "Pundit number of comments"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:91
+msgid ""
+"\n"
+"Number of comments an user needs to post to be awarded the Pundit badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:96
+msgid "Self Learner up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:97
+msgid ""
+"\n"
+"Number of up votes an answer from the question author needs to have for the author to be awarded the Self Learner badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:102
+msgid "Strunk and White updates"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:103
+msgid ""
+"\n"
+"Number of question or answer updates an user needs to make to be awarded the Strunk & White badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:108
+msgid "Enlightened up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:109
+msgid ""
+"\n"
+"Number of up votes an accepted answer needs to have for the author to be awarded the Enlightened badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:114
+msgid "Guru up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:115
+msgid ""
+"\n"
+"Number of up votes an accepted answer needs to have for the author to be awarded the Guru badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:120
+msgid "Necromancer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:121
+msgid ""
+"\n"
+"Number of up votes an answer needs to have for the author to be awarded the Necromancer badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:126
+msgid "Necromancer difference in days"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:127
+msgid ""
+"\n"
+"Difference in days betwen the posted date of a question and an answer for the answer author to be awarded the Necromancer badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:132
+msgid "Taxonomist usage count"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:133
+msgid ""
+"\n"
+"How many usages a tag needs to have for the tag creator to be awarded the Taxonomist badge. \n"
+msgstr ""
+
+#: forum_modules/facebookauth/authentication.py:31
+msgid "Sorry, your Facebook session has expired, please try again"
+msgstr ""
+
+#: forum_modules/facebookauth/authentication.py:33
+msgid "The authentication with Facebook connect failed due to an invalid signature"
+msgstr ""
+
+#: forum_modules/facebookauth/authentication.py:35
+msgid "The authentication with Facebook connect failed, cannot find authentication tokens"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:75
+msgid "Please enter valid username and password (both are case-sensitive)."
+msgstr ""
+
+#: forum_modules/localauth/forms.py:79
+msgid "This account is inactive."
+msgstr ""
+
+#: forum_modules/localauth/forms.py:81
+msgid "Login failed."
+msgstr ""
+
+#: forum_modules/localauth/forms.py:85
+msgid "This user is not a valid user"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:88
+msgid "Please enter username and password"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:90
+msgid "Please enter your password"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:92
+msgid "Please enter user name"
+msgstr ""
+
+#: forum_modules/localauth/urls.py:7
+msgid "local/"
+msgstr ""
+
+#: forum_modules/localauth/views.py:33
+msgid "A validation email has been sent to your email address. "
+msgstr ""
+
+#: forum_modules/oauthauth/consumer.py:33
+msgid "Error, the oauth token is not on the server"
+msgstr ""
+
+#: forum_modules/oauthauth/consumer.py:38
+msgid "Something went wrong! Auth tokens do not match"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:40
+msgid "Sorry, but your input is not a valid OpenId"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:92
+msgid "The OpenId authentication request was canceled"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:94
+msgid "The OpenId authentication failed: "
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:96
+msgid "Setup needed"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:98
+msgid "The OpenId authentication failed with an unknown status: "
+msgstr ""
+
+#: forum_modules/openidauth/templates/openidurl.html:7
+msgid "Enter your OpenId Url"
+msgstr ""
+
+#: forum_modules/project_badges/badges.py:9
+#, python-format
+msgid "Got %s upvotes in a question tagged with \"bug\""
+msgstr ""
+
+#: forum_modules/recaptcha/formfield.py:20
+msgid "Invalid captcha"
+msgstr ""
+
+#: forum_modules/sximporter/importer.py:39
+#, python-format
+msgid "Unknown user %(number)d"
+msgstr ""
+
+#: forum_modules/sximporter/urls.py:8
+msgid "sximporter/"
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:7
+msgid "SX Importer"
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:10
+msgid "Welcome to Stack Exchange dump importer."
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:16
+msgid "Your user id in stack exchange"
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:20
+msgid "Merge users with same user name and email"
+msgstr ""
+
+#: locale/phrases.py:1
+msgid "Test Phrase 1"
+msgstr ""
+
+#: locale/phrases.py:2
+msgid "Test Phrase 2"
+msgstr ""
+
+#: locale/phrases.py:3
+msgid "Test Phrase 3"
+msgstr ""
+
+#: locale/phrases.py:4
+msgid "Test Phrase n"
+msgstr ""
+
+#~ msgid "email update message subject"
+#~ msgstr "news from Q&A forum"
+
+#~ msgid "%(name)s, this is an update message header for a question"
+#~ msgid_plural "%(name)s, this is an update message header for %(num)d questions"
+#~ msgstr[0] "<p>Dear %(name)s,</p></p>The following question has been updated on the Q&A forum:</p>"
+#~ msgstr[1] "<p>Dear %(name)s,</p><p>The following %(num)d questions have been updated on the Q&A forum:</p>"
+
+#~ msgid "go to %(link)s to change frequency of email updates or %(email)s administrator"
+#~ msgstr "<p>Please remember that you can always <a href='%(link)s'>adjust</a> frequency of the email updates or turn them off entirely.<br/>If you believe that this message was sent in an error, please email about it the forum administrator at %(email)s.</p><p>Sincerely,</p><p>Your friendly Q&A forum server.</p>"
+
+#~ msgid "Account: change password"
+#~ msgstr "Change your password"
+
+#~ msgid "list of unanswered questions"
+#~ msgstr "unanswered questions"
+
+#~ msgid "Notify me once a day when there are any new answers"
+#~ msgstr "<strong>Notify me</strong> once a day by email when there are any new answers or updates"
+
+#~ msgid "Notify me weekly when there are any new answers"
+#~ msgstr "<strong>Notify me</strong> weekly when there are any new answers or updates"
+
+#~ msgid ""
+#~ "\n"
+#~ "                You can always adjust frequency of email updates from your %(profile_url)s\n"
+#~ "                "
+#~ msgstr ""
+#~ "\n"
+#~ "(note: you can always <a href='%(profile_url)s?sort=email_subscriptions'>adjust frequency</a> of email updates)"
+
+#~ msgid "please ask a relevant question"
+#~ msgstr "ask a question relevant to the CNPROG community"
+
+#~ msgid ""
+#~ "\n"
+#~ "                    have total %(q_num)s questions containing %(searchtitle)s in full text\n"
+#~ "                    "
+#~ msgid_plural ""
+#~ "\n"
+#~ "                    have total %(q_num)s questions containing %(searchtitle)s in full text\n"
+#~ "                    "
+#~ msgstr[0] ""
+#~ "\n"
+#~ "<div class=\"questions-count\">%(q_num)s</div><p>question containing <strong><span class=\"darkred\">%(searchtitle)s</span></strong></p>"
+#~ msgstr[1] ""
+#~ "\n"
+#~ "<div class=\"questions-count\">%(q_num)s</div><p>questions containing <strong><span class=\"darkred\">%(searchtitle)s</span></strong></p>"
+
+#~ msgid ""
+#~ "\n"
+#~ "                    have total %(q_num)s questions containing %(searchtitle)s\n"
+#~ "                    "
+#~ msgid_plural ""
+#~ "\n"
+#~ "                    have total %(q_num)s questions containing %(searchtitle)s\n"
+#~ "                    "
+#~ 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>"
+
+#~ msgid ""
+#~ "\n"
+#~ "                    have total %(q_num)s unanswered questions\n"
+#~ "                    "
+#~ msgid_plural ""
+#~ "\n"
+#~ "                    have total %(q_num)s unanswered questions\n"
+#~ "                    "
+#~ msgstr[0] ""
+#~ "\n"
+#~ "<div class=\"questions-count\">%(q_num)s</div><p>question without an accepted answer</p>"
+#~ msgstr[1] ""
+#~ "\n"
+#~ "<div class=\"questions-count\">%(q_num)s</div><p>questions without an accepted answer</p>"
+
+#~ msgid "latest questions info"
+#~ msgstr "<strong>Newest</strong> questions are shown first."
+
+#~ msgid "Most recently answered ones are shown first."
+#~ msgstr "<strong>Most recently answered</strong> questions are shown first."
+
+#~ msgid "Stop sending email"
+#~ msgstr "Stop Email"
+
+#~ msgid "change %(email)s info"
+#~ msgstr "<span class=\"strong big\">Enter your new email into the box below</span> if you'd like to use another email for <strong>update subscriptions</strong>.<br>Currently you are using <strong>%(email)s</strong>"
+
+#~ msgid "here is why email is required, see %(gravatar_faq_url)s"
+#~ msgstr "<span class='strong big'>Please enter your email address in the box below.</span> Valid email address is required on this Q&amp;A forum. If you like, you can <strong>receive updates</strong> on interesting questions or entire forum via email. Also, your email is used to create a unique <a href='%(gravatar_faq_url)s'><strong>gravatar</strong></a> image for your account. Email addresses are never shown or otherwise shared with anybody else."
+
+#~ msgid "Your Email"
+#~ msgstr "<strong>Your Email</strong> (<i>must be valid, never shown to others</i>)"
+
+#~ msgid "validate %(email)s info or go to %(change_email_url)s"
+#~ msgstr "<span class=\"strong big\">An email with a validation link has been sent to %(email)s.</span> Please <strong>follow the emailed link</strong> with your web browser. Email validation is necessary to help insure the proper use of email on <span class=\"orange\">Q&amp;A</span>. If you would like to use <strong>another email</strong>, please <a href='%(change_email_url)s'><strong>change it again</strong></a>."
+
+#~ msgid "old %(email)s kept, if you like go to %(change_email_url)s"
+#~ msgstr "<span class=\"strong big\">Your email address %(email)s has not been changed.</span> If you decide to change it later - you can always do it by editing it in your user profile or by using the <a href='%(change_email_url)s'><strong>previous form</strong></a> again."
+
+#~ msgid "your current %(email)s can be used for this"
+#~ msgstr "<span class='big strong'>Your email address is now set to %(email)s.</span> Updates on the questions that you like most will be sent to this address. Email notifications are sent once a day or less frequently - only when there are any news."
+
+#~ msgid "thanks for verifying email"
+#~ msgstr "<span class=\"big strong\">Thank you for verifying your email!</span> Now you can <strong>ask</strong> and <strong>answer</strong> questions. Also if you find a very interesting question you can <strong>subscribe for the updates</strong> - then will be notified about changes <strong>once a day</strong> or less frequently."
+
+#~ msgid "email key not sent"
+#~ msgstr "Validation email not sent"
+
+#~ msgid "email key not sent %(email)s change email here %(change_link)s"
+#~ msgstr "<span class='big strong'>Your current email address %(email)s has been validated before</span> so the new key was not sent. You can <a href='%(change_link)s'>change</a> email used for update subscriptions if necessary."
+
+#~ msgid "register new %(provider)s account info, see %(gravatar_faq_url)s"
+#~ msgstr "<p><span class=\"big strong\">You are here for the first time with your %(provider)s login.</span> Please create your <strong>screen name</strong> and save your <strong>email</strong> address. Saved email address will let you <strong>subscribe for the updates</strong> on the most interesting questions and will be used to create and retrieve your unique avatar image - <a href='%(gravatar_faq_url)s'><strong>gravatar</strong></a>.</p>"
+
+#~ msgid ""
+#~ "%(username)s already exists, choose another name for \n"
+#~ "                            %(provider)s. Email is required too, see %(gravatar_faq_url)s\n"
+#~ "                        "
+#~ msgstr "<p><span class='strong big'>Oops... looks like screen name %(username)s is already used in another account.</span></p><p>Please choose another screen name to use with your %(provider)s login. Also, a valid email address is required on the <span class='orange'>Q&amp;A</span> forum. Your email is used to create a unique <a href='%(gravatar_faq_url)s'><strong>gravatar</strong></a> image for your account. If you like, you can <strong>receive updates</strong> on the interesting questions or entire forum by email. Email addresses are never shown or otherwise shared with anybody else.</p>"
+
+#~ msgid "register new external %(provider)s account info, see %(gravatar_faq_url)s"
+#~ msgstr "<p><span class=\"big strong\">You are here for the first time with your %(provider)s login.</span></p><p>You can either keep your <strong>screen name</strong> the same as your %(provider)s login name  or choose some other nickname.</p><p>Also, please save a valid <strong>email</strong> address. With the email you can <strong>subscribe for the updates</strong> on the most interesting questions. Email address is also used to create and retrieve your unique avatar image - <a href='%(gravatar_faq_url)s'><strong>gravatar</strong></a>.</p>"
+
+#~ msgid "register new Facebook connect account info, see %(gravatar_faq_url)s"
+#~ msgstr "<p><span class=\"big strong\">You are here for the first time with your Facebook login.</span> Please create your <strong>screen name</strong> and save your <strong>email</strong> address. Saved email address will let you <strong>subscribe for the updates</strong> on the most interesting questions and will be used to create and retrieve your unique avatar image - <a href='%(gravatar_faq_url)s'><strong>gravatar</strong></a>.</p>"
+
+#~ msgid "password recovery information"
+#~ msgstr "<span class='big strong'>Forgot you password? No problems - just get a new one!</span><br/>Please follow the following steps:<br/>&bull; submit your user name below and check your email<br/>&bull; <strong>follow the activation link</strong> for the new password - sent to you by email and login with the suggested password<br/>&bull; at this you might want to change your password to something you can remember better"
+
+#~ msgid "Reset password"
+#~ msgstr "Send me a new password"
+
+#~ msgid ""
+#~ "email explanation how to use new %(password)s for %(username)s\n"
+#~ "with the %(key_link)s"
+#~ msgstr ""
+#~ "To change your password, please follow these steps:\n"
+#~ "* visit this link: %(key_link)s\n"
+#~ "* login with user name %(username)s and password %(password)s\n"
+#~ "* go to your user profile and set the password to something you can remember"
+
+#~ msgid ""
+#~ "\n"
+#~ "                Your answer to %(title)s %(summary)s will be posted once you log in\n"
+#~ "                "
+#~ msgstr ""
+#~ "\n"
+#~ "<span class=\"strong big\">Your answer to </span> <i>\"<strong>%(title)s</strong> %(summary)s...\"</i> <span class=\"strong big\">is saved and will be posted once you log in.</span>"
+
+#~ msgid ""
+#~ "Your question \n"
+#~ "                %(title)s %(summary)s will be posted once you log in\n"
+#~ "                "
+#~ msgstr "<span class=\"strong big\">Your question</span> <i>\"<strong>%(title)s</strong> %(summary)s...\"</i> <span class=\"strong big\">is saved and will be posted once you log in.</span>"
+
+#~ msgid "Enter your <span id=\"enter_your_what\">Provider user name</span>"
+#~ msgstr "<span class=\"big strong\">Enter your </span><span id=\"enter_your_what\" class='big strong'>Provider user name</span><br/><span class='grey'>(or select another login method above)</span>"
+
+#~ msgid "Enter your <a class=\"openid_logo\" href=\"http://openid.net\">OpenID</a> web address"
+#~ msgstr "<span class=\"big strong\">Enter your <a class=\"openid_logo\" href=\"http://openid.net\">OpenID</a> web address</span><br/><span class='grey'>(or choose another login method above)</span>"
+
+#~ msgid "Enter your login name and password"
+#~ msgstr "<span class='big strong'>Enter your CNPROG login and password</span><br/><span class='grey'>(or select your OpenID provider above)</span>"
+
+#~ msgid "subscription saved, %(email)s needs validation, see %(details_url)s"
+#~ msgstr "Your subscription is saved, but email address %(email)s needs to be validated, please see <a href='%(details_url)s'>more details here</a>"
+
+#~ msgid "Incorrect username."
+#~ msgstr "sorry, there is no such user name"
+
+#~ msgid "your email needs to be validated see %(details_url)s"
+#~ msgstr "Your email needs to be validated. Please see details <a id='validate_email_alert' href='%(details_url)s'>here</a>."
+
+#~ msgid "Email verification subject line"
+#~ msgstr "Verification Email from Q&A forum"
+
+#~ msgid "first time greeting with %(url)s"
+#~ msgstr "Hello and welcome to OSQA - <a href='%(url)s'>please join us</a>!"
+
+#~ msgid "have %(num_q)s unanswered questions"
+#~ msgstr "<div class=\"questions-count\">%(num_q)s</div>questions <strong>without accepted answers</strong>"
+
+#~ msgid ""
+#~ "\n"
+#~ "\t\t\t\thave total %(q_num)s questions\n"
+#~ "\t\t\t\t"
+#~ msgid_plural ""
+#~ "\n"
+#~ "\t\t\t\thave total %(q_num)s questions\n"
+#~ "\t\t\t\t"
+#~ msgstr[0] ""
+#~ "\n"
+#~ "<div class=\"questions-count\">%(q_num)s</div><p>question</p>"
+#~ msgstr[1] ""
+#~ "\n"
+#~ "<div class=\"questions-count\">%(q_num)s</div><p>questions</p>"
diff --git a/forum/modules/template_loader.py/locale/es/LC_MESSAGES/django.mo b/forum/modules/template_loader.py/locale/es/LC_MESSAGES/django.mo
new file mode 100644 (file)
index 0000000..bcf4a26
Binary files /dev/null and b/forum/modules/template_loader.py/locale/es/LC_MESSAGES/django.mo differ
diff --git a/forum/modules/template_loader.py/locale/es/LC_MESSAGES/django.po b/forum/modules/template_loader.py/locale/es/LC_MESSAGES/django.po
new file mode 100644 (file)
index 0000000..57b8ba9
--- /dev/null
@@ -0,0 +1,4285 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+# 
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-04-28 16:53-0400\n"
+"PO-Revision-Date: 2010-04-28 18:14\n"
+"Last-Translator: <court@dzone.com>\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"
+"X-Translated-Using: django-rosetta 0.5.3\n"
+
+#: forum/const.py:8
+msgid "duplicate question"
+msgstr "cuestión duplicado"
+
+#: forum/const.py:9
+msgid "question is off-topic or not relevant"
+msgstr "pregunta es fuera de tema o no pertinentes"
+
+#: forum/const.py:10
+msgid "too subjective and argumentative"
+msgstr "demasiado subjetivo y argumentativo"
+
+#: forum/const.py:11
+msgid "is not an answer to the question"
+msgstr "no es una respuesta a la pregunta"
+
+#: forum/const.py:12
+msgid "the question is answered, right answer was accepted"
+msgstr "la pregunta es contestada, respuesta correcta fue aceptada"
+
+#: forum/const.py:13
+msgid "problem is not reproducible or outdated"
+msgstr "problema no es reproducible o no actualizados"
+
+#: forum/const.py:14
+msgid "question contains offensive inappropriate, or malicious remarks"
+msgstr "cuestión contiene inadecuado ofensivo o los comentarios maliciosos"
+
+#: forum/const.py:15
+msgid "spam or advertising"
+msgstr "spam o publicidad"
+
+#: forum/const.py:71 forum/skins/default/templates/osqaadmin/index.html:21
+msgid "question"
+msgstr "cuestión"
+
+#: forum/const.py:72 forum/skins/default/templates/book.html:110
+#: forum/skins/default/templates/osqaadmin/index.html:26
+msgid "answer"
+msgstr "respuesta"
+
+#: forum/const.py:73
+msgid "commented question"
+msgstr "comentó cuestión"
+
+#: forum/const.py:74
+msgid "commented answer"
+msgstr "comentó respuesta"
+
+#: forum/const.py:75
+msgid "edited question"
+msgstr "cuestión editado"
+
+#: forum/const.py:76
+msgid "edited answer"
+msgstr "editado respuesta"
+
+#: forum/const.py:77
+msgid "received award"
+msgstr "premio recibido"
+
+#: forum/const.py:78
+msgid "marked best answer"
+msgstr "marcada mejor respuesta"
+
+#: forum/const.py:79
+msgid "upvoted"
+msgstr "upvoted"
+
+#: forum/const.py:80
+msgid "downvoted"
+msgstr "downvoted"
+
+#: forum/const.py:81
+msgid "upvote canceled"
+msgstr "upvote cancela"
+
+#: forum/const.py:82
+msgid "downvote canceled"
+msgstr "downvote cancela"
+
+#: forum/const.py:83
+msgid "deleted question"
+msgstr "cuestión eliminado"
+
+#: forum/const.py:84
+msgid "deleted answer"
+msgstr "respuesta eliminado"
+
+#: forum/const.py:85
+msgid "marked offensive"
+msgstr "marcado ofensiva"
+
+#: forum/const.py:86
+msgid "updated tags"
+msgstr "etiquetas de actualización"
+
+#: forum/const.py:87
+msgid "selected favorite"
+msgstr "marcados como favoritos"
+
+#: forum/const.py:88
+msgid "completed user profile"
+msgstr "Perfil de usuario completa"
+
+#: forum/const.py:89
+msgid "email update sent to user"
+msgstr "correo electrónico de actualización enviado al usuario"
+
+#: forum/const.py:93
+msgid "question_answered"
+msgstr "question_answered"
+
+#: forum/const.py:94
+msgid "question_commented"
+msgstr "question_commented"
+
+#: forum/const.py:95
+msgid "answer_commented"
+msgstr "answer_commented"
+
+#: forum/const.py:96
+msgid "answer_accepted"
+msgstr "answer_accepted"
+
+#: forum/const.py:100
+msgid "[closed]"
+msgstr "[Cerrado]"
+
+#: forum/const.py:101
+msgid "[deleted]"
+msgstr "[Suprimido]"
+
+#: forum/const.py:102
+msgid "initial version"
+msgstr "versión inicial"
+
+#: forum/const.py:103
+msgid "retagged"
+msgstr "retagged"
+
+#: forum/const.py:111
+msgid "Instantly"
+msgstr "Instantáneamente"
+
+#: forum/const.py:112
+msgid "Daily"
+msgstr "Diario"
+
+#: forum/const.py:113
+msgid "Weekly"
+msgstr "Semanal"
+
+#: forum/const.py:114
+msgid "No notifications"
+msgstr "N notificaciones"
+
+#: forum/feed.py:18
+msgid " - "
+msgstr ""
+
+#: forum/feed.py:18
+msgid "latest questions"
+msgstr ""
+
+#: forum/forms.py:21 forum/skins/default/templates/answer_edit_tips.html:35
+#: forum/skins/default/templates/answer_edit_tips.html:39
+#: forum/skins/default/templates/question_edit_tips.html:37
+#: forum/skins/default/templates/question_edit_tips.html:42
+msgid "title"
+msgstr ""
+
+#: forum/forms.py:22
+msgid "please enter a descriptive title for your question"
+msgstr ""
+
+#: forum/forms.py:27
+msgid "title must be > 10 characters"
+msgstr ""
+
+#: forum/forms.py:36
+msgid "content"
+msgstr ""
+
+#: forum/forms.py:42
+msgid "question content must be > 10 characters"
+msgstr ""
+
+#: forum/forms.py:52 forum/skins/default/templates/header.html:31
+#: forum/skins/default/templates/header.html:56
+msgid "tags"
+msgstr ""
+
+#: forum/forms.py:54
+msgid "Tags are short keywords, with no spaces within. Up to five tags can be used."
+msgstr ""
+
+#: forum/forms.py:61 forum/skins/default/templates/question_retag.html:43
+msgid "tags are required"
+msgstr ""
+
+#: forum/forms.py:67
+msgid "please use 5 tags or less"
+msgstr ""
+
+#: forum/forms.py:72
+msgid "tags must be shorter than 20 characters"
+msgstr ""
+
+#: forum/forms.py:74
+msgid "please use following characters in tags: letters 'a-z', numbers, and characters '.-_#'"
+msgstr ""
+
+#: forum/forms.py:84
+#: forum/skins/default/templates/post_contributor_info.html:7
+#: forum/skins/default/templates/question_summary_list_roll.html:26
+#: forum/skins/default/templates/question_summary_list_roll.html:38
+msgid "community wiki"
+msgstr ""
+
+#: forum/forms.py:85
+msgid "if you choose community wiki option, the question and answer do not generate points and name of author will not be shown"
+msgstr ""
+
+#: forum/forms.py:101
+msgid "update summary:"
+msgstr ""
+
+#: forum/forms.py:102
+msgid "enter a brief summary of your revision (e.g. fixed spelling, grammar, improved style, this field is optional)"
+msgstr ""
+
+#: forum/forms.py:105
+msgid "Automatically accept user's contributions for the email updates"
+msgstr ""
+
+#: forum/forms.py:118
+msgid "Your name:"
+msgstr ""
+
+#: forum/forms.py:119
+msgid "Email (not shared with anyone):"
+msgstr ""
+
+#: forum/forms.py:120
+msgid "Your message:"
+msgstr ""
+
+#: forum/forms.py:202
+msgid "this email does not have to be linked to gravatar"
+msgstr ""
+
+#: forum/forms.py:204
+msgid "Screen name"
+msgstr ""
+
+#: forum/forms.py:205
+msgid "Real name"
+msgstr ""
+
+#: forum/forms.py:206
+msgid "Website"
+msgstr ""
+
+#: forum/forms.py:207
+msgid "Location"
+msgstr ""
+
+#: forum/forms.py:208
+msgid "Date of birth"
+msgstr ""
+
+#: forum/forms.py:208
+msgid "will not be shown, used to calculate age, format: YYYY-MM-DD"
+msgstr ""
+
+#: forum/forms.py:209 forum/skins/default/templates/account_settings.html:21
+msgid "Profile"
+msgstr ""
+
+#: forum/forms.py:240 forum/forms.py:241
+msgid "this email has already been registered, please use another one"
+msgstr ""
+
+#: forum/subscriptions.py:41
+#, python-format
+msgid "New question on %(app_name)s"
+msgstr ""
+
+#: forum/subscriptions.py:73
+#, python-format
+msgid "New answer to '%(question_title)s'"
+msgstr ""
+
+#: forum/subscriptions.py:112
+#, python-format
+msgid "New comment on %(question_title)s"
+msgstr ""
+
+#: forum/subscriptions.py:136
+#, python-format
+msgid "An answer to '%(question_title)s' was accepted"
+msgstr ""
+
+#: forum/subscriptions.py:156
+#, python-format
+msgid "%(username)s is a new member on %(app_name)s"
+msgstr ""
+
+#: forum/urls.py:44
+msgid "upfiles/"
+msgstr ""
+
+#: forum/urls.py:49
+msgid "about/"
+msgstr ""
+
+#: forum/urls.py:50
+msgid "faq/"
+msgstr ""
+
+#: forum/urls.py:51
+msgid "privacy/"
+msgstr ""
+
+#: forum/urls.py:52
+msgid "logout/"
+msgstr ""
+
+#: forum/urls.py:53 forum/urls.py:54
+msgid "answers/"
+msgstr ""
+
+#: forum/urls.py:53 forum/urls.py:58 forum/urls.py:98
+#: forum/skins/default/templates/users/info.html:44
+msgid "edit/"
+msgstr ""
+
+#: forum/urls.py:54 forum/urls.py:74
+msgid "revisions/"
+msgstr ""
+
+#: forum/urls.py:55 forum/urls.py:56 forum/urls.py:57 forum/urls.py:58
+#: forum/urls.py:59 forum/urls.py:60 forum/urls.py:61 forum/urls.py:74
+msgid "questions/"
+msgstr ""
+
+#: forum/urls.py:56 forum_modules/books/urls.py:8
+msgid "ask/"
+msgstr ""
+
+#: forum/urls.py:57
+msgid "unanswered/"
+msgstr ""
+
+#: forum/urls.py:59
+msgid "close/"
+msgstr ""
+
+#: forum/urls.py:60
+msgid "reopen/"
+msgstr ""
+
+#: forum/urls.py:61
+msgid "answer/"
+msgstr ""
+
+#: forum/urls.py:63
+msgid "vote/"
+msgstr ""
+
+#: forum/urls.py:64
+msgid "like_comment/"
+msgstr ""
+
+#: forum/urls.py:65
+msgid "comment/"
+msgstr ""
+
+#: forum/urls.py:66
+msgid "delete_comment/"
+msgstr ""
+
+#: forum/urls.py:67
+msgid "accept_answer/"
+msgstr ""
+
+#: forum/urls.py:68
+msgid "mark_favorite/"
+msgstr ""
+
+#: forum/urls.py:69
+msgid "flag/"
+msgstr ""
+
+#: forum/urls.py:70
+msgid "delete/"
+msgstr ""
+
+#: forum/urls.py:71
+msgid "subscribe/"
+msgstr ""
+
+#: forum/urls.py:72
+msgid "matching_tags/"
+msgstr ""
+
+#: forum/urls.py:75
+msgid "command/"
+msgstr ""
+
+#: forum/urls.py:78
+msgid "question/"
+msgstr ""
+
+#: forum/urls.py:79 forum/urls.py:80
+msgid "tags/"
+msgstr ""
+
+#: forum/urls.py:82 forum/urls.py:86
+msgid "mark-tag/"
+msgstr ""
+
+#: forum/urls.py:82
+msgid "interesting/"
+msgstr ""
+
+#: forum/urls.py:86
+msgid "ignored/"
+msgstr ""
+
+#: forum/urls.py:90
+msgid "unmark-tag/"
+msgstr ""
+
+#: forum/urls.py:96 forum/urls.py:98 forum/urls.py:100 forum/urls.py:101
+#: forum/urls.py:102 forum/urls.py:103 forum/urls.py:104 forum/urls.py:105
+#: forum/models/user.py:124
+msgid "users/"
+msgstr ""
+
+#: forum/urls.py:97
+msgid "moderate-user/"
+msgstr ""
+
+#: forum/urls.py:100
+msgid "subscriptions/"
+msgstr ""
+
+#: forum/urls.py:101
+msgid "favorites/"
+msgstr ""
+
+#: forum/urls.py:102
+msgid "reputation/"
+msgstr ""
+
+#: forum/urls.py:103
+msgid "votes/"
+msgstr ""
+
+#: forum/urls.py:104
+msgid "recent/"
+msgstr ""
+
+#: forum/urls.py:107 forum/urls.py:108
+msgid "badges/"
+msgstr ""
+
+#: forum/urls.py:109
+msgid "messages/"
+msgstr ""
+
+#: forum/urls.py:109
+msgid "markread/"
+msgstr ""
+
+#: forum/urls.py:111
+msgid "nimda/"
+msgstr ""
+
+#: forum/urls.py:113
+msgid "upload/"
+msgstr ""
+
+#: forum/urls.py:114
+msgid "search/"
+msgstr ""
+
+#: forum/urls.py:115
+msgid "feedback/"
+msgstr ""
+
+#: forum/urls.py:119 forum/urls.py:120 forum/urls.py:121 forum/urls.py:122
+#: forum/urls.py:123 forum/urls.py:124 forum/urls.py:125 forum/urls.py:126
+#: forum/urls.py:127 forum/urls.py:128 forum/urls.py:129 forum/urls.py:130
+#: forum_modules/localauth/urls.py:7
+msgid "account/"
+msgstr ""
+
+#: forum/urls.py:119 forum/urls.py:121 forum/urls.py:122
+msgid "signin/"
+msgstr ""
+
+#: forum/urls.py:120
+msgid "signout/"
+msgstr ""
+
+#: forum/urls.py:123
+msgid "done/"
+msgstr ""
+
+#: forum/urls.py:124 forum_modules/localauth/urls.py:7
+msgid "register/"
+msgstr ""
+
+#: forum/urls.py:125
+msgid "validate/"
+msgstr ""
+
+#: forum/urls.py:126 forum/urls.py:127
+msgid "tempsignin/"
+msgstr ""
+
+#: forum/urls.py:128
+msgid "authsettings/"
+msgstr ""
+
+#: forum/urls.py:129 forum/urls.py:130
+msgid "providers/"
+msgstr ""
+
+#: forum/urls.py:129
+msgid "remove/"
+msgstr ""
+
+#: forum/urls.py:130
+msgid "add/"
+msgstr ""
+
+#: forum/urls.py:133 forum/urls.py:134 forum/urls.py:135 forum/urls.py:136
+#: forum/urls.py:137 forum_modules/sximporter/urls.py:8
+msgid "admin/"
+msgstr ""
+
+#: forum/urls.py:134
+msgid "denormalize/"
+msgstr ""
+
+#: forum/urls.py:135
+msgid "go_bootstrap/"
+msgstr ""
+
+#: forum/urls.py:136
+msgid "go_defaults/"
+msgstr ""
+
+#: forum/authentication/forms.py:21
+msgid "Your account email"
+msgstr ""
+
+#: forum/authentication/forms.py:23
+msgid "You cannot leave this field blank"
+msgstr ""
+
+#: forum/authentication/forms.py:24 forum/utils/forms.py:107
+msgid "please enter a valid email address"
+msgstr ""
+
+#: forum/authentication/forms.py:32
+msgid "Sorry, but this email is not on our database."
+msgstr ""
+
+#: forum/authentication/forms.py:40
+msgid "okay, let's try!"
+msgstr ""
+
+#: forum/authentication/forms.py:41
+msgid "no OSQA community email please, thanks"
+msgstr ""
+
+#: forum/authentication/forms.py:44
+msgid "please choose one of the options above"
+msgstr ""
+
+#: forum/authentication/forms.py:51
+msgid "Current password"
+msgstr ""
+
+#: forum/authentication/forms.py:62
+msgid "Old password is incorrect.                     Please enter the correct password."
+msgstr ""
+
+#: forum/management/commands/send_email_alerts.py:56
+msgid "Daily digest"
+msgstr ""
+
+#: forum/middleware/anon_user.py:34
+#, python-format
+msgid "First time here? Check out the <a href=\"%s\">FAQ</a>!"
+msgstr ""
+
+#: forum/models/question.py:30
+msgid "[closed] "
+msgstr ""
+
+#: forum/models/question.py:33
+msgid "[deleted] "
+msgstr ""
+
+#: forum/models/repute.py:13 forum/skins/default/templates/badges.html:53
+msgid "gold"
+msgstr ""
+
+#: forum/models/repute.py:14 forum/skins/default/templates/badges.html:61
+msgid "silver"
+msgstr ""
+
+#: forum/models/repute.py:15 forum/skins/default/templates/badges.html:68
+msgid "bronze"
+msgstr ""
+
+#: forum/models/tag.py:28
+msgid "interesting"
+msgstr ""
+
+#: forum/models/tag.py:28
+msgid "ignored"
+msgstr ""
+
+#: forum/models/user.py:255
+#: forum/skins/default/templates/post_contributor_info.html:19
+msgid "asked"
+msgstr ""
+
+#: forum/models/user.py:257
+#: forum/skins/default/templates/post_contributor_info.html:22
+msgid "answered"
+msgstr ""
+
+#: forum/models/user.py:259
+msgid "marked an answer"
+msgstr ""
+
+#: forum/models/user.py:261
+msgid "edited a question"
+msgstr ""
+
+#: forum/models/user.py:263
+msgid "commented a question"
+msgstr ""
+
+#: forum/models/user.py:265
+msgid "commented an answer"
+msgstr ""
+
+#: forum/models/user.py:267
+msgid "edited an answer"
+msgstr ""
+
+#: forum/models/user.py:269
+msgid "received badge"
+msgstr ""
+
+#: forum/settings/__init__.py:20
+msgid "Badges config"
+msgstr ""
+
+#: forum/settings/__init__.py:20
+msgid "Configure badges on your OSQA site."
+msgstr ""
+
+#: forum/settings/basic.py:9
+msgid "Basic Settings"
+msgstr ""
+
+#: forum/settings/basic.py:9
+msgid "The basic settings for your application"
+msgstr ""
+
+#: forum/settings/basic.py:12
+msgid "Application logo"
+msgstr ""
+
+#: forum/settings/basic.py:13
+msgid "Your site main logo."
+msgstr ""
+
+#: forum/settings/basic.py:17
+msgid "Favicon"
+msgstr ""
+
+#: forum/settings/basic.py:18
+msgid "Your site favicon."
+msgstr ""
+
+#: forum/settings/basic.py:22
+msgid "Application title"
+msgstr ""
+
+#: forum/settings/basic.py:23
+msgid "The title of your application that will show in the browsers title bar"
+msgstr ""
+
+#: forum/settings/basic.py:26
+msgid "Application short name"
+msgstr ""
+
+#: forum/settings/basic.py:30
+msgid "Application keywords"
+msgstr ""
+
+#: forum/settings/basic.py:31
+msgid "The meta keywords that will be available through the HTML meta tags."
+msgstr ""
+
+#: forum/settings/basic.py:34
+msgid "Application description"
+msgstr ""
+
+#: forum/settings/basic.py:35
+msgid "The description of your application"
+msgstr ""
+
+#: forum/settings/basic.py:39
+msgid "Application intro"
+msgstr ""
+
+#: forum/settings/basic.py:40
+msgid "The introductory page that is visible in the sidebar for anonymous users."
+msgstr ""
+
+#: forum/settings/basic.py:44
+msgid "Copyright notice"
+msgstr ""
+
+#: forum/settings/basic.py:45
+msgid "The copyright notice visible at the footer of your page."
+msgstr ""
+
+#: forum/settings/basic.py:48
+msgid "Maximum length of comment"
+msgstr ""
+
+#: forum/settings/basic.py:49
+msgid "The maximum length a user can enter for a comment."
+msgstr ""
+
+#: forum/settings/email.py:5
+msgid "Email Settings"
+msgstr ""
+
+#: forum/settings/email.py:5
+msgid "Email server and other email related settings."
+msgstr ""
+
+#: forum/settings/email.py:8
+msgid "Email Server"
+msgstr ""
+
+#: forum/settings/email.py:9
+msgid "The SMTP server through which your application will be sending emails."
+msgstr ""
+
+#: forum/settings/email.py:13
+msgid "Email Port"
+msgstr ""
+
+#: forum/settings/email.py:14
+msgid "The port on which your SMTP server is listening to. Usually this is 25, but can be something else."
+msgstr ""
+
+#: forum/settings/email.py:18
+msgid "Email User"
+msgstr ""
+
+#: forum/settings/email.py:19
+msgid "The username for your SMTP connection."
+msgstr ""
+
+#: forum/settings/email.py:23
+msgid "Email Password"
+msgstr ""
+
+#: forum/settings/email.py:24
+msgid "The password for your SMTP connection."
+msgstr ""
+
+#: forum/settings/email.py:29
+msgid "Use TLS"
+msgstr ""
+
+#: forum/settings/email.py:30
+msgid "Does your SMTP server usFes TLS for authentication."
+msgstr ""
+
+#: forum/settings/email.py:34
+msgid "Site 'from' email address"
+msgstr ""
+
+#: forum/settings/email.py:35
+msgid "The address that will show up on the 'from' field on emails sent by your website."
+msgstr ""
+
+#: forum/settings/email.py:39
+msgid "Email subject prefix"
+msgstr ""
+
+#: forum/settings/email.py:40
+msgid "Every email sent through your website will have the subject prefixed by this string. It's usually a good idea to have such a prefix so your users can easilly set up a filter on their email clients."
+msgstr ""
+
+#: forum/settings/extkeys.py:4
+msgid "External Keys"
+msgstr ""
+
+#: forum/settings/extkeys.py:4
+msgid "Keys for various external providers that your application may optionally use."
+msgstr ""
+
+#: forum/settings/extkeys.py:7
+msgid "Google sitemap code"
+msgstr ""
+
+#: forum/settings/extkeys.py:8
+msgid "This is the code you get when you register your site at <a href='https://www.google.com/webmasters/tools/'>Google webmaster central</a>."
+msgstr ""
+
+#: forum/settings/extkeys.py:12
+msgid "Google analytics key"
+msgstr ""
+
+#: forum/settings/extkeys.py:13
+msgid "Your Google analytics key. You can get one at the <a href='http://www.google.com/analytics/'>Google analytics official website</a>"
+msgstr ""
+
+#: forum/settings/forms.py:40
+msgid "Change this:"
+msgstr ""
+
+#: forum/settings/minrep.py:4
+msgid "Minimum reputation config"
+msgstr ""
+
+#: forum/settings/minrep.py:4
+msgid "Configure the minimum reputation required to perform certain actions on your site."
+msgstr ""
+
+#: forum/settings/minrep.py:7
+msgid "Minimum reputation to vote up"
+msgstr ""
+
+#: forum/settings/minrep.py:8
+msgid "The minimum reputation an user must have to be allowed to vote up."
+msgstr ""
+
+#: forum/settings/minrep.py:11
+msgid "Minimum reputation to vote down"
+msgstr ""
+
+#: forum/settings/minrep.py:12
+msgid "The minimum reputation an user must have to be allowed to vote down."
+msgstr ""
+
+#: forum/settings/minrep.py:15
+msgid "Minimum reputation to flag a post"
+msgstr ""
+
+#: forum/settings/minrep.py:16
+msgid "The minimum reputation an user must have to be allowed to flag a post."
+msgstr ""
+
+#: forum/settings/minrep.py:19
+msgid "Minimum reputation to comment"
+msgstr ""
+
+#: forum/settings/minrep.py:20
+msgid "The minimum reputation an user must have to be allowed to comment a post."
+msgstr ""
+
+#: forum/settings/minrep.py:23
+msgid "Minimum reputation to like a comment"
+msgstr ""
+
+#: forum/settings/minrep.py:24
+msgid "The minimum reputation an user must have to be allowed to \"like\" a comment."
+msgstr ""
+
+#: forum/settings/minrep.py:27
+msgid "Minimum reputation to upload"
+msgstr ""
+
+#: forum/settings/minrep.py:28
+msgid "The minimum reputation an user must have to be allowed to upload a file."
+msgstr ""
+
+#: forum/settings/minrep.py:31
+msgid "Minimum reputation to close own question"
+msgstr ""
+
+#: forum/settings/minrep.py:32
+msgid "The minimum reputation an user must have to be allowed to close his own question."
+msgstr ""
+
+#: forum/settings/minrep.py:35
+msgid "Minimum reputation to reopen own question"
+msgstr ""
+
+#: forum/settings/minrep.py:36
+msgid "The minimum reputation an user must have to be allowed to reopen his own question."
+msgstr ""
+
+#: forum/settings/minrep.py:39
+msgid "Minimum reputation to retag others questions"
+msgstr ""
+
+#: forum/settings/minrep.py:40
+msgid "The minimum reputation an user must have to be allowed to retag others questions."
+msgstr ""
+
+#: forum/settings/minrep.py:43
+msgid "Minimum reputation to edit wiki posts"
+msgstr ""
+
+#: forum/settings/minrep.py:44
+msgid "The minimum reputation an user must have to be allowed to edit community wiki posts."
+msgstr ""
+
+#: forum/settings/minrep.py:47
+msgid "Minimum reputation to edit others posts"
+msgstr ""
+
+#: forum/settings/minrep.py:48
+msgid "The minimum reputation an user must have to be allowed to edit others posts."
+msgstr ""
+
+#: forum/settings/minrep.py:51
+msgid "Minimum reputation to close others posts"
+msgstr ""
+
+#: forum/settings/minrep.py:52
+msgid "The minimum reputation an user must have to be allowed to close others posts."
+msgstr ""
+
+#: forum/settings/minrep.py:55
+msgid "Minimum reputation to delete comments"
+msgstr ""
+
+#: forum/settings/minrep.py:56
+msgid "The minimum reputation an user must have to be allowed to delete comments."
+msgstr ""
+
+#: forum/settings/minrep.py:59
+msgid "Minimum reputation to view offensive flags"
+msgstr ""
+
+#: forum/settings/minrep.py:60
+msgid "The minimum reputation an user must have to view offensive flags."
+msgstr ""
+
+#: forum/settings/repgain.py:4
+msgid "Reputation gains and losses config"
+msgstr ""
+
+#: forum/settings/repgain.py:4
+msgid "Configure the reputation points a user may gain or lose upon certain actions."
+msgstr ""
+
+#: forum/settings/repgain.py:7
+msgid "Initial reputation"
+msgstr ""
+
+#: forum/settings/repgain.py:8
+msgid "The initial reputation an user gets when he first signs in."
+msgstr ""
+
+#: forum/settings/repgain.py:12
+msgid "Maximum reputation a user can gain in one day for being upvoted."
+msgstr ""
+
+#: forum/settings/repgain.py:15
+msgid "Rep gain by upvoted"
+msgstr ""
+
+#: forum/settings/repgain.py:16
+msgid "Reputation a user gains for having one of his posts up voted."
+msgstr ""
+
+#: forum/settings/repgain.py:19
+msgid "Rep lost bu upvote canceled"
+msgstr ""
+
+#: forum/settings/repgain.py:20
+msgid "Reputation a user loses for having one of the upvotes on his posts canceled."
+msgstr ""
+
+#: forum/settings/repgain.py:23
+msgid "Rep lost by downvoted"
+msgstr ""
+
+#: forum/settings/repgain.py:24
+msgid "Reputation a user loses for having one of his posts down voted."
+msgstr ""
+
+#: forum/settings/repgain.py:27
+msgid "Rep lost by downvoting"
+msgstr ""
+
+#: forum/settings/repgain.py:28
+msgid "Reputation a user loses for down voting a post."
+msgstr ""
+
+#: forum/settings/repgain.py:31
+msgid "Rep gain by downvote canceled"
+msgstr ""
+
+#: forum/settings/repgain.py:32
+msgid "Reputation a user gains for having one of the downvotes on his posts canceled."
+msgstr ""
+
+#: forum/settings/repgain.py:35
+msgid "Rep gain by canceling downvote"
+msgstr ""
+
+#: forum/settings/repgain.py:36
+msgid "Reputation a user gains for canceling a downvote."
+msgstr ""
+
+#: forum/settings/repgain.py:39
+msgid "Rep gain by accepted answer"
+msgstr ""
+
+#: forum/settings/repgain.py:40
+msgid "Reputation a user gains for having one of his answers accepted."
+msgstr ""
+
+#: forum/settings/repgain.py:43
+msgid "Rep lost by accepted canceled"
+msgstr ""
+
+#: forum/settings/repgain.py:44
+msgid "Reputation a user loses for having one of his accepted answers canceled."
+msgstr ""
+
+#: forum/settings/repgain.py:47
+msgid "Rep gain by accepting answer"
+msgstr ""
+
+#: forum/settings/repgain.py:48
+msgid "Reputation a user gains for accepting an answer to one of his questions."
+msgstr ""
+
+#: forum/settings/repgain.py:51
+msgid "Rep lost by canceling accepted"
+msgstr ""
+
+#: forum/settings/repgain.py:52
+msgid "Reputation a user loses by canceling an accepted answer."
+msgstr ""
+
+#: forum/settings/repgain.py:55
+msgid "Rep lost by post flagged"
+msgstr ""
+
+#: forum/settings/repgain.py:56
+msgid "Reputation a user loses by having one of his posts flagged."
+msgstr ""
+
+#: forum/settings/repgain.py:59
+msgid "Rep lost by post flagged and hidden"
+msgstr ""
+
+#: forum/settings/repgain.py:60
+msgid "Reputation a user loses by having the last revision of one of his posts flagged the enough number of times to hide the post."
+msgstr ""
+
+#: forum/settings/repgain.py:63
+msgid "Rep lost by post flagged and deleted"
+msgstr ""
+
+#: forum/settings/repgain.py:64
+msgid "Reputation a user loses by having the last revision of one of his posts flagged the enough number of times to delete the post."
+msgstr ""
+
+#: forum/settings/upload.py:5
+msgid "File upload settings"
+msgstr ""
+
+#: forum/settings/upload.py:5
+msgid "File uploads related settings."
+msgstr ""
+
+#: forum/settings/upload.py:8
+msgid "Uploaded files folder"
+msgstr ""
+
+#: forum/settings/upload.py:9
+msgid "The filesystem path where uploaded files will be stored. Please note that this folder must exist."
+msgstr ""
+
+#: forum/settings/upload.py:12
+msgid "Uploaded files alias"
+msgstr ""
+
+#: forum/settings/upload.py:13
+msgid "The url alias for uploaded files. Notice that if you change this setting, you'll need to restart your site."
+msgstr ""
+
+#: forum/settings/upload.py:16
+msgid "Max file size"
+msgstr ""
+
+#: forum/settings/upload.py:17
+msgid "The maximum allowed file size for uploads in mb."
+msgstr ""
+
+#: forum/settings/voting.py:4
+msgid "Voting rules"
+msgstr ""
+
+#: forum/settings/voting.py:4
+msgid "Configure the voting rules on your site."
+msgstr ""
+
+#: forum/settings/voting.py:7
+msgid "Maximum votes per day"
+msgstr ""
+
+#: forum/settings/voting.py:8
+msgid "The maximum number of votes an user can cast per day."
+msgstr ""
+
+#: forum/settings/voting.py:11
+msgid "Start warning about votes left"
+msgstr ""
+
+#: forum/settings/voting.py:12
+msgid "From how many votes left should an user start to be warned about it."
+msgstr ""
+
+#: forum/settings/voting.py:15
+msgid "Maximum flags per day"
+msgstr ""
+
+#: forum/settings/voting.py:16
+msgid "The maximum number of times an can flag a post per day."
+msgstr ""
+
+#: forum/settings/voting.py:19
+msgid "Flag count to hide post"
+msgstr ""
+
+#: forum/settings/voting.py:20
+msgid "How many times a post needs to be flagged to be hidden from the main page."
+msgstr ""
+
+#: forum/settings/voting.py:23
+msgid "Flag count to delete post"
+msgstr ""
+
+#: forum/settings/voting.py:24
+msgid "How many times a post needs to be flagged to be deleted."
+msgstr ""
+
+#: forum/settings/voting.py:27
+msgid "Days to cancel a vote"
+msgstr ""
+
+#: forum/settings/voting.py:28
+msgid "How many days an user can cancel a vote after he originaly casted it."
+msgstr ""
+
+#: forum/skins/default/templates/404.html:24
+msgid "Sorry, could not find the page you requested."
+msgstr ""
+
+#: forum/skins/default/templates/404.html:26
+msgid "This might have happened for the following reasons:"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:28
+msgid "this question or answer has been deleted;"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:29
+msgid "url has error - please check it;"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:30
+msgid "the page you tried to visit is protected or you don't have sufficient points, see"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:31
+msgid "if you believe this error 404 should not have occured, please"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:32
+msgid "report this problem"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:41
+#: forum/skins/default/templates/500.html:27
+msgid "back to previous page"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:42
+msgid "see all questions"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:43
+msgid "see all tags"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:22
+msgid "sorry, system error"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:24
+msgid "system error log is recorded, error will be fixed as soon as possible"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:25
+msgid "please report the error to the site administrators if you wish"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:28
+msgid "see latest questions"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:29
+msgid "see tags"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:12
+#: forum/skins/default/templates/book.html:105
+#: forum/skins/default/templates/question_summary_list_roll.html:14
+#: forum/skins/default/templates/question_list/item.html:10
+#: forum/views/commands.py:82
+msgid "votes"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:14
+msgid "this answer has been accepted to be correct"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:16
+#: forum/skins/default/templates/question_summary_list_roll.html:13
+#: forum/skins/default/templates/question_list/item.html:14
+msgid "answers"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:20
+#: forum/skins/default/templates/book.html:115
+#: forum/skins/default/templates/question_summary_list_roll.html:15
+#: forum/skins/default/templates/question_list/item.html:18
+msgid "views"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:34
+#: forum/skins/default/templates/question.html:234
+#: forum/skins/default/templates/question_summary_list_roll.html:52
+#: forum/skins/default/templates/tags.html:49
+#: forum/skins/default/templates/question_list/item.html:29
+msgid "see questions tagged"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:34
+#: forum/skins/default/templates/book.html:125
+#: forum/skins/default/templates/question.html:234
+#: forum/skins/default/templates/question_summary_list_roll.html:52
+#: forum/skins/default/templates/tags.html:49
+#: forum/skins/default/templates/question_list/item.html:29
+msgid "using tags"
+msgstr ""
+
+#: forum/skins/default/templates/about.html:5
+#: forum/skins/default/templates/about.html:9
+msgid "About"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:4
+msgid "Account functions"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:29
+#: forum/skins/default/templates/auth/auth_settings.html:31
+msgid "Change password"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:30
+msgid "Give your  account a new password."
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:32
+msgid "Change email "
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:33
+msgid "Add or update the email address associated with your account."
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:35
+msgid "Change OpenID"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:36
+msgid "Change openid associated to your account"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:39
+msgid "Delete account"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:40
+msgid "Erase your username and all your data from website"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:5
+#: forum/skins/default/templates/answer_edit.html:39
+msgid "Edit answer"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:18
+#: forum/skins/default/templates/answer_edit.html:21
+#: forum/skins/default/templates/ask.html:19
+#: forum/skins/default/templates/ask.html:22
+#: forum/skins/default/templates/question_edit.html:19
+#: forum/skins/default/templates/question_edit.html:22
+msgid "hide preview"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:21
+#: forum/skins/default/templates/ask.html:22
+#: forum/skins/default/templates/question_edit.html:22
+msgid "show preview"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:39
+#: forum/skins/default/templates/question_edit.html:63
+#: forum/skins/default/templates/question_retag.html:56
+#: forum/skins/default/templates/revisions_answer.html:36
+#: forum/skins/default/templates/revisions_question.html:35
+msgid "back"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:44
+#: forum/skins/default/templates/question_edit.html:68
+#: forum/skins/default/templates/revisions_answer.html:50
+#: forum/skins/default/templates/revisions_question.html:49
+msgid "revision"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:47
+#: forum/skins/default/templates/question_edit.html:72
+msgid "select revision"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:54
+#: forum/skins/default/templates/ask.html:93
+#: forum/skins/default/templates/question.html:184
+#: forum/skins/default/templates/question_edit.html:89
+msgid "Toggle the real time Markdown editor preview"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:54
+#: forum/skins/default/templates/ask.html:93
+#: forum/skins/default/templates/question.html:185
+#: forum/skins/default/templates/question_edit.html:89
+msgid "toggle preview"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:63
+#: forum/skins/default/templates/question_edit.html:115
+#: forum/skins/default/templates/question_retag.html:77
+msgid "Save edit"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:64
+#: forum/skins/default/templates/close.html:29
+#: forum/skins/default/templates/feedback.html:50
+#: forum/skins/default/templates/question_edit.html:116
+#: forum/skins/default/templates/question_retag.html:78
+#: forum/skins/default/templates/reopen.html:30
+#: forum/skins/default/templates/users/edit.html:87
+msgid "Cancel"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:4
+msgid "answer tips"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:7
+msgid "please make your answer relevant to this community"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:10
+msgid "try to give an answer, rather than engage into a discussion"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:13
+msgid "please try to provide details"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:16
+#: forum/skins/default/templates/question_edit_tips.html:18
+msgid "be clear and concise"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:20
+#: forum/skins/default/templates/question_edit_tips.html:22
+msgid "see frequently asked questions"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:26
+#: forum/skins/default/templates/question_edit_tips.html:28
+msgid "Markdown tips"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:29
+#: forum/skins/default/templates/question_edit_tips.html:31
+msgid "*italic* or __italic__"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:32
+#: forum/skins/default/templates/question_edit_tips.html:34
+msgid "**bold** or __bold__"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:35
+#: forum/skins/default/templates/question_edit_tips.html:37
+msgid "link"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:35
+#: forum/skins/default/templates/answer_edit_tips.html:39
+#: forum/skins/default/templates/question_edit_tips.html:37
+#: forum/skins/default/templates/question_edit_tips.html:42
+msgid "text"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:39
+#: forum/skins/default/templates/question_edit_tips.html:42
+msgid "image"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:43
+#: forum/skins/default/templates/question_edit_tips.html:46
+msgid "numbered list:"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:48
+#: forum/skins/default/templates/question_edit_tips.html:51
+msgid "basic HTML tags are also supported"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:52
+#: forum/skins/default/templates/question_edit_tips.html:55
+msgid "learn more about Markdown"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:5
+#: forum/skins/default/templates/ask.html:57
+msgid "Ask a question"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:64
+msgid "login to post question info"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:70
+#, python-format
+msgid ""
+"must have valid %(email)s to post, \n"
+"                            see %(email_validation_faq_url)s\n"
+"                            "
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:108
+msgid "(required)"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:115
+msgid "Login/signup to post your question"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:117
+msgid "Ask your question"
+msgstr ""
+
+#: forum/skins/default/templates/badge.html:6
+#: forum/skins/default/templates/badge.html:17
+msgid "Badge"
+msgstr ""
+
+#: forum/skins/default/templates/badge.html:26
+msgid "The users have been awarded with badges:"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:6
+msgid "Badges summary"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:17
+msgid "Badges"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:21
+msgid "Community gives you awards for your questions, answers and votes."
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:22
+#, python-format
+msgid ""
+"Below is the list of available badges and number \n"
+"    of times each type of badge has been awarded. Give us feedback at %(feedback_faq_url)s.\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:50
+msgid "Community badges"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:56
+msgid "gold badge description"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:64
+msgid "silver badge description"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:67
+msgid "bronze badge: often given as a special honor"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:71
+msgid "bronze badge description"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:7
+msgid "reading channel"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:26
+msgid "[author]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:30
+msgid "[publisher]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:34
+msgid "[publication date]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:38
+msgid "[price]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:39
+msgid "currency unit"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:42
+msgid "[pages]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:43
+msgid "pages abbreviation"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:46
+msgid "[tags]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:56
+msgid "author blog"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:62
+msgid "book directory"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:66
+msgid "buy online"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:79
+msgid "reader questions"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:82
+msgid "ask the author"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:88
+#: forum/skins/default/templates/book.html:93
+msgid "this question was selected as favorite"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:88
+#: forum/skins/default/templates/book.html:93
+msgid "number of times"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:108
+msgid "the answer has been accepted to be correct"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:147
+msgid "subscribe to book RSS feed"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:147
+msgid "subscribe to the questions feed"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:6
+#: forum/skins/default/templates/close.html:16
+msgid "Close question"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:19
+msgid "Close the question"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:25
+msgid "Reasons"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:28
+msgid "OK to close"
+msgstr ""
+
+#: forum/skins/default/templates/email_base.html:31
+msgid "home"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:11
+msgid "Frequently Asked Questions "
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:16
+msgid "What kinds of questions can I ask here?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:17
+msgid "Most importantly - questions should be <strong>relevant</strong> to this community."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:18
+msgid "Before asking the question - please make sure to use search to see whether your question has alredy been answered."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:21
+msgid "What questions should I avoid asking?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:22
+msgid "Please avoid asking questions that are not relevant to this community, too subjective and argumentative."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:27
+msgid "What should I avoid in my answers?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:28
+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 ""
+
+#: forum/skins/default/templates/faq.html:32
+msgid "Who moderates this community?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:33
+msgid "The short answer is: <strong>you</strong>."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:34
+msgid "This website is moderated by the users."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:35
+msgid "The reputation system allows users earn the authorization to perform a variety of moderation tasks."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:40
+msgid "How does reputation system work?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:41
+msgid "Rep system summary"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:42
+msgid "For example, if you ask an interesting question or give a helpful answer, your input will be upvoted. On the other hand if the answer is misleading - it will be downvoted. Each vote in favor will generate <strong>10</strong> points, each vote against will subtract <strong>2</strong> points. There is a limit of <strong>200</strong> points that can be accumulated per question or answer. The table below explains reputation point requirements for each type of moderation task."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:53
+#: forum/skins/default/templates/users/votes.html:15
+#: forum/views/commands.py:77
+msgid "upvote"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:57
+msgid "use tags"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:62
+msgid "add comments"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:66
+#: forum/skins/default/templates/users/votes.html:17
+#: forum/views/commands.py:77
+msgid "downvote"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:69
+msgid "open and close own questions"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:73
+msgid "retag questions"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:78
+msgid "edit community wiki questions"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:83
+msgid "edit any answer"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:87
+msgid "open any closed question"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:91
+msgid "delete any comment"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:95
+msgid "delete any questions and answers and perform other moderation tasks"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:103
+msgid "how to validate email title"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:105
+#, python-format
+msgid "how to validate email info with %(send_email_key_url)s %(gravatar_faq_url)s"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:110
+msgid "what is gravatar"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:111
+msgid "gravatar faq info"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:114
+msgid "To register, do I need to create new password?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:115
+msgid "No, you don't have to. You can login through any service that supports OpenID, e.g. Google, Yahoo, AOL, etc."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:116
+msgid "Login now!"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:121
+msgid "Why other people can edit my questions/answers?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:122
+msgid "Goal of this site is..."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:122
+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 ""
+
+#: forum/skins/default/templates/faq.html:123
+msgid "If this approach is not for you, we respect your choice."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:127
+msgid "Still have questions?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:128
+#, python-format
+msgid "Please ask your question at %(ask_question_url)s, help make our community better!"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:130
+#: forum/skins/default/templates/header.html:30
+#: forum/skins/default/templates/header.html:55 forum/views/readers.py:76
+msgid "questions"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:130
+msgid "."
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:6
+msgid "Feedback"
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:11
+msgid "Give us your feedback!"
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:17
+#, python-format
+msgid ""
+"\n"
+"            <span class='big strong'>Dear %(user_name)s</span>, we look forward to hearing your feedback. \n"
+"            Please type and send us your message below.\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:24
+msgid ""
+"\n"
+"            <span class='big strong'>Dear visitor</span>, we look forward to hearing your feedback.\n"
+"            Please type and send us your message below.\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:41
+msgid "(this field is required)"
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:49
+msgid "Send Feedback"
+msgstr ""
+
+#: forum/skins/default/templates/footer.html:7
+#: forum/skins/default/templates/header.html:16
+#: forum/skins/default/templates/index.html:12
+msgid "about"
+msgstr ""
+
+#: forum/skins/default/templates/footer.html:8
+#: forum/skins/default/templates/header.html:17
+#: forum/skins/default/templates/index.html:13
+#: forum/skins/default/templates/question_edit_tips.html:22
+msgid "faq"
+msgstr ""
+
+#: forum/skins/default/templates/footer.html:9
+msgid "privacy policy"
+msgstr ""
+
+#: forum/skins/default/templates/footer.html:18
+msgid "give feedback"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:9
+msgid "administration"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:12
+msgid "logout"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:14
+msgid "login"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:24
+msgid "back to home page"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:32
+#: forum/skins/default/templates/header.html:57
+msgid "users"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:33
+#: forum/skins/default/templates/users/signature.html:9
+#: forum/skins/default/templates/users/signature.html:15
+#: forum/skins/default/templates/users/signature.html:21
+#: forum/templatetags/extra_tags.py:167 forum/templatetags/extra_tags.py:196
+msgid "badges"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:34
+msgid "unanswered questions"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:36
+msgid "ask a question"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:51
+msgid "search"
+msgstr ""
+
+#: forum/skins/default/templates/index.html:9
+msgid "welcome to "
+msgstr ""
+
+#: forum/skins/default/templates/logout.html:6
+#: forum/skins/default/templates/logout.html:16
+msgid "Logout"
+msgstr ""
+
+#: forum/skins/default/templates/logout.html:19
+msgid "As a registered user you can login with your OpenID, log out of the site or permanently remove your account."
+msgstr ""
+
+#: forum/skins/default/templates/logout.html:20
+msgid "Logout now"
+msgstr ""
+
+#: forum/skins/default/templates/notarobot.html:3
+msgid "Please prove that you are a Human Being"
+msgstr ""
+
+#: forum/skins/default/templates/notarobot.html:10
+msgid "I am a Human Being"
+msgstr ""
+
+#: forum/skins/default/templates/pagesize.html:6
+msgid "posts per page"
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:6
+#: forum/skins/default/templates/paginator.html:7
+msgid "previous"
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:19
+msgid "current page"
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:22
+#: forum/skins/default/templates/paginator.html:29
+msgid "page number "
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:22
+#: forum/skins/default/templates/paginator.html:29
+msgid "number - make blank in english"
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:33
+msgid "next page"
+msgstr ""
+
+#: forum/skins/default/templates/post_contributor_info.html:9
+#, python-format
+msgid ""
+"\n"
+"                one revision\n"
+"            "
+msgid_plural ""
+"\n"
+"                %(rev_count)s revisions\n"
+"            "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/post_contributor_info.html:24
+msgid "posted"
+msgstr ""
+
+#: forum/skins/default/templates/post_contributor_info.html:45
+msgid "updated"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:6
+#: forum/skins/default/templates/privacy.html:11
+msgid "Privacy policy"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:15
+msgid "general message about privacy"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:18
+msgid "Site Visitors"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:20
+msgid "what technical information is collected about visitors"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:23
+msgid "Personal Information"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:25
+msgid "details on personal information policies"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:28
+msgid "Other Services"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:30
+msgid "details on sharing data with third parties"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:35
+msgid "cookie policy details"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:37
+msgid "Policy Changes"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:38
+msgid "how privacy policies can be changed"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:70
+#: forum/skins/default/templates/sidebar/recent_tags.html:9
+#, python-format
+msgid "see questions tagged '%(tagname)s'"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:87
+#, python-format
+msgid "The question has been closed for the following reason \"%(close_reason)s\" by"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:89
+#, python-format
+msgid "close date %(closed_at)s"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:97
+#, python-format
+msgid ""
+"\n"
+"                    One Answer:\n"
+"                    "
+msgid_plural ""
+"\n"
+"                    %(counter)s Answers:\n"
+"                    "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/question.html:105
+msgid "oldest answers will be shown first"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:105
+msgid "oldest answers"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:107
+msgid "newest answers will be shown first"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:107
+msgid "newest answers"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:109
+msgid "most voted answers will be shown first"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:109
+msgid "popular answers"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:157
+msgid "Your answer"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:159
+msgid "Be the first one to answer this question!"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:165
+msgid "you can answer anonymously and then login"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:169
+msgid "answer your own question only to give an answer"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:171
+msgid "please only give an answer, no discussions"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:207
+msgid "Login/Signup to Post Your Answer"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:210
+msgid "Answer Your Own Question"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:212
+msgid "Answer the question"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:229
+msgid "Question tags"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:239
+msgid "question asked"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:242
+msgid "question was seen"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:242
+msgid "times"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:245
+msgid "last updated"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:250
+msgid "Related questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_edit.html:5
+#: forum/skins/default/templates/question_edit.html:63
+msgid "Edit question"
+msgstr ""
+
+#: forum/skins/default/templates/question_edit_tips.html:4
+msgid "question tips"
+msgstr ""
+
+#: forum/skins/default/templates/question_edit_tips.html:9
+#, python-format
+msgid ""
+"\n"
+"                ask a question relevant to the %(app_title)s community \n"
+"                "
+msgstr ""
+
+#: forum/skins/default/templates/question_edit_tips.html:15
+msgid "please try provide enough details"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:5
+#: forum/skins/default/templates/question_retag.html:56
+msgid "Change tags"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:44
+msgid "up to 5 tags, less than 20 characters each"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:86
+msgid "Why use and modify tags?"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:89
+msgid "tags help us keep Questions organized"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:97
+msgid "tag editors receive special awards from the community"
+msgstr ""
+
+#: forum/skins/default/templates/questions.html:7
+msgid "Questions"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:6
+#: forum/skins/default/templates/reopen.html:16
+msgid "Reopen question"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:19
+msgid "Open the previously closed question"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:22
+msgid "The question was closed for the following reason "
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:22
+msgid "reason - leave blank in english"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:22
+msgid "on "
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:22
+msgid "date closed"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:29
+msgid "Reopen this question"
+msgstr ""
+
+#: forum/skins/default/templates/revisions_answer.html:7
+#: forum/skins/default/templates/revisions_answer.html:36
+#: forum/skins/default/templates/revisions_question.html:7
+#: forum/skins/default/templates/revisions_question.html:35
+msgid "Revision history"
+msgstr ""
+
+#: forum/skins/default/templates/revisions_answer.html:48
+#: forum/skins/default/templates/revisions_question.html:47
+msgid "click to hide/show revision"
+msgstr ""
+
+#: forum/skins/default/templates/revisions_answer.html:56
+#: forum/templatetags/node_tags.py:62
+msgid "edit"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:3
+msgid "Subscription"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:8
+msgid "You were automatically subscribed to this question."
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:10
+msgid "You are subscribed to this question."
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:13
+msgid "You are not subscribed to this question."
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:18
+#: forum/views/commands.py:323
+msgid "unsubscribe me"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:20
+#: forum/views/commands.py:323
+msgid "subscribe me"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:24
+#, python-format
+msgid ""
+"\n"
+"            (you can adjust your notification settings on your <a href=\"%(profile_url)s?sort=email_subscriptions\">profile</a>)\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:29
+msgid "Once you sign in you will be able to subscribe for any updates here"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:4
+#: forum/skins/default/templates/question_list/tag_selector.html:6
+msgid "Interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:10
+#: forum/skins/default/templates/tag_selector.html:27
+#: forum/skins/default/templates/question_list/related_tags.html:9
+#: forum/skins/default/templates/question_list/tag_selector.html:12
+#: forum/skins/default/templates/question_list/tag_selector.html:29
+#, python-format
+msgid "see questions tagged '%(tag_name)s'"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:14
+#: forum/skins/default/templates/question_list/tag_selector.html:16
+#, python-format
+msgid "remove '%(tag_name)s' from the list of interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:20
+#: forum/skins/default/templates/tag_selector.html:37
+#: forum/skins/default/templates/question_list/tag_selector.html:22
+#: forum/skins/default/templates/question_list/tag_selector.html:39
+msgid "Add"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:21
+#: forum/skins/default/templates/question_list/tag_selector.html:23
+msgid "Ignored tags"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:31
+#: forum/skins/default/templates/question_list/tag_selector.html:33
+#, python-format
+msgid "remove '%(tag_name)s' from the list of ignored tags"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:40
+#: forum/skins/default/templates/question_list/tag_selector.html:42
+msgid "keep ignored questions hidden"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:6
+#: forum/skins/default/templates/tags.html:30
+msgid "Tag list"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:32
+msgid "sorted alphabetically"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:32
+msgid "by name"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:33
+msgid "sorted by frequency of tag use"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:33
+msgid "by popularity"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:39
+msgid "All tags matching query"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:39
+msgid "all tags - make this empty in english"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:42
+msgid "Nothing found"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:5
+#: forum/skins/default/templates/auth/auth_settings.html:7
+msgid "Authentication settings"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:9
+msgid "These are the external authentication providers currently associated with your account."
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:12
+msgid "remove"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:17
+msgid "You currently have no external authentication provider associated with your account."
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:19
+msgid "Add new provider"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:21
+msgid "This is where you can change your password. Make sure you remember it!"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:24
+msgid "You can set up a password for your account, so you can login using standard username and password!"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:31
+msgid "Create password"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:5
+msgid "Connect your OpenID with this site"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:8
+msgid "Connect your OpenID with your account on this site"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:12
+msgid "You are here for the first time with "
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:13
+msgid "Please create your screen name and save your email address. Saved email address will let you subscribe for the updates on the most interesting questions and will be used to create and retrieve your unique avatar image. "
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:15
+msgid "This account already exists, please use another."
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:30
+msgid "Sorry, looks like we have some errors:"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:47
+msgid "Screen name label"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:54
+msgid "Email address label"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:60
+#: forum/skins/default/templates/auth/signup.html:18
+msgid "receive updates motivational blurb"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:64
+#: forum/skins/default/templates/auth/signup.html:22
+msgid "please select one of the options above"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:67
+msgid "Tag filter tool will be your right panel, once you log in."
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:68
+msgid "create account"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:77
+msgid "Existing account"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:78
+msgid "user name"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:79
+msgid "password"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:86
+msgid "Register"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:87
+msgid "Forgot your password?"
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:6
+#: forum/skins/default/templates/auth/temp_login_email.html:6
+msgid "Greetings from the Q&A forum"
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:8
+msgid "To make use of the Forum, please follow the link below:"
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:12
+msgid "Following the link above will help us verify your email address."
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:14
+#: forum/skins/default/templates/auth/temp_login_email.html:14
+msgid ""
+"If you beleive that this message was sent in mistake -\n"
+"    no further action is needed. Just ingore this email, we apologize\n"
+"    for any inconvenience"
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:18
+#: forum/skins/default/templates/auth/temp_login_email.html:18
+#: forum/skins/default/templates/notifications/answeraccepted.html:15
+#: forum/skins/default/templates/notifications/newanswer.html:25
+#: forum/skins/default/templates/notifications/newcomment.html:32
+#: forum/skins/default/templates/notifications/newmember.html:15
+#: forum/skins/default/templates/notifications/newquestion.html:25
+msgid ""
+"Sincerely,<br />\n"
+"    Forum Administrator"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:6
+msgid "Login"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:24
+msgid "User login"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:36
+#: forum/skins/default/templates/auth/signin.html:86
+#: forum/skins/default/templates/auth/signin.html:92
+msgid "Or..."
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:39
+msgid "Click to sign in through any of these services."
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:44
+msgid "Validate my email after I login."
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:94
+msgid "Click"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:94
+msgid "if you're having troubles signing in."
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:98
+msgid "Enter your "
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:154
+msgid "Why use OpenID?"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:157
+msgid "with openid it is easier"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:160
+msgid "reuse openid"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:163
+msgid "openid is widely adopted"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:166
+msgid "openid is supported open standard"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:171
+msgid "Find out more"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:172
+msgid "Get OpenID"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:4
+msgid "Signup"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:8
+msgid "Create login name and password"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:10
+msgid "Traditional signup info"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:31
+msgid "Create Account"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:32
+msgid "or"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:33
+msgid "return to login page"
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_email.html:8
+msgid "You're seeing this because someone requested a temporary login link"
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_email.html:12
+msgid "Following the link above will give you access to your account."
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:5
+msgid "Request temporary login key"
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:7
+msgid "Account: request temporary login key"
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:8
+msgid ""
+"\n"
+"    If you're experiencing problems accessing your account, or if you forgot your password,\n"
+"    here you can request a temporary login key. Fill out your account email and we'll send you a temporary access link that\n"
+"    will enable you to access your account. This token is valid only once and for a limited period of time.\n"
+" "
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:25
+msgid "Send link"
+msgstr ""
+
+#: forum/skins/default/templates/node/accept_button.html:5
+#, python-format
+msgid "%(who)s has selected this answer as the correct answer"
+msgstr ""
+
+#: forum/skins/default/templates/node/accept_button.html:5
+msgid "mark this answer as the accepted answer"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:22
+msgid "I like this comment (click again to cancel)"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:26
+msgid "Edit comment"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:30
+msgid "Delete comment"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:42
+#, python-format
+msgid "showing %(showing)s of %(total)s"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:44
+msgid "show all"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:47
+msgid "add new comment"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:55
+msgid " add comment"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:58
+#, python-format
+msgid ""
+"\n"
+"                have <span class=\"comments-char-left-count\">%(max_length)s</span> characters left\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:71
+msgid "just now"
+msgstr ""
+
+#: forum/skins/default/templates/node/favorite_mark.html:3
+msgid "mark/unmark this question as favorite (click again to cancel)"
+msgstr ""
+
+#: forum/skins/default/templates/node/vote_buttons.html:3
+msgid "I like this post (click again to cancel)"
+msgstr ""
+
+#: forum/skins/default/templates/node/vote_buttons.html:7
+msgid "current number of votes"
+msgstr ""
+
+#: forum/skins/default/templates/node/vote_buttons.html:10
+msgid "I dont like this post (click again to cancel)"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/answeraccepted.html:6
+#: forum/skins/default/templates/notifications/digest.html:7
+#: forum/skins/default/templates/notifications/newanswer.html:6
+#: forum/skins/default/templates/notifications/newcomment.html:6
+#: forum/skins/default/templates/notifications/newmember.html:6
+#: forum/skins/default/templates/notifications/newquestion.html:6
+msgid "Hello"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/answeraccepted.html:9
+#, python-format
+msgid ""
+"\n"
+"        Just to let you know that %(accepter)s has just accepted %(answer_author)s's answer on his question\n"
+"        <a href=\"%(app_url)s%(question_url)s\">%(question_title)s</a>:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:9
+#, python-format
+msgid ""
+"\n"
+"    This is the %(digest_type)s activity digest for %(app_title)s\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:15
+#, python-format
+msgid ""
+"\n"
+"            %(nusers_count)s new user%(nusers_count_pluralize)s joined the %(app_title)s community:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:28
+#, python-format
+msgid ""
+"\n"
+"            %(question_count)s of your subscriptions have updates:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:35
+msgid "On question "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:37
+#, python-format
+msgid ""
+"\n"
+"                    %(answer_count)s new answer%(answer_count_pluralize)s\n"
+"                "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:42
+#, python-format
+msgid ""
+"\n"
+"                    %(comment_count)s new comment%(comment_count_pluralize)s\n"
+"                "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:46
+msgid "on your own post(s)"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:50
+msgid "an answer was accepted"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:59
+#, python-format
+msgid ""
+"\n"
+"            %(question_count)s new question%(question_count_pluralize)s\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:63
+msgid "matching your interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:65
+msgid "posted :"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:71
+#, python-format
+msgid ""
+"\n"
+"                    Posted by %(author_name)s in %(question_time)s\n"
+"                "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:7
+#, python-format
+msgid ""
+"\n"
+"    Hello, this is a %(site_title)s forum feedback message\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:13
+msgid "Sender"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:15
+#: forum/skins/default/templates/notifications/feedback.html:18
+#: forum/skins/default/templates/users/info.html:93
+msgid "email"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:17
+msgid "anonymous"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:25
+msgid "Message body:"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newanswer.html:9
+#, python-format
+msgid ""
+"\n"
+"        %(author_name)s has just posted a new answer on %(app_title)s to the question\n"
+"        <a href=\"%(app_url)s%(question_url)s\">%(question_title)s\"</a>:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newanswer.html:20
+#: forum/skins/default/templates/notifications/newcomment.html:28
+#: forum/skins/default/templates/notifications/newquestion.html:20
+msgid ""
+"\n"
+"        Don't forget to come over and cast your vote.\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newcomment.html:9
+#, python-format
+msgid ""
+"\n"
+"            %(author_name)s has just posted a comment on\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newcomment.html:14
+#, python-format
+msgid ""
+"\n"
+"                the answer posted by <a href=\"%(app_url)s%(poster_url)s\">%(poster_name)s</a> to\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newcomment.html:19
+#, python-format
+msgid ""
+"\n"
+"             the question  <a href=\"%(app_url)s%(question_url)s\">%(question_title)s</a>\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newmember.html:9
+#, python-format
+msgid ""
+"\n"
+"        %(newmember_name)s has just joined %(app_title)s. You can visit %(newmember_name)s's profile using the following link: <br />\n"
+"        <a href=\"%(app_url)s%(newmember_url)s\">%(newmember_name)s profile</a>\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newquestion.html:9
+#, python-format
+msgid ""
+"\n"
+"        %(author_name)s has just posted a new question on %(app_title)s, with title\n"
+"        <a href=\"%(app_url)s%(question_url)s\">%(question_title)s</a> and tagged <em>%(question_tags)s</em>:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/base.html:13
+msgid "OSQA administration area"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/base.html:26
+msgid "Administration menu"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:7
+msgid "Dashboard"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:10
+msgid "Welcome to the OSQA administration area."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:17
+msgid "Site statistics"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:21
+#: forum/skins/default/templates/osqaadmin/index.html:26
+msgid "in the last 24 hours"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:31
+msgid "user"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:31
+msgid "joined in the last 24 hours"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:37
+msgid "Site status"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:42
+msgid "Your site is running in bootstrap mode, click the button bellow to revert to defaults."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:45
+msgid "Your site is running in standard mode, click the button bellow to run in bootstrap mode."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:47
+msgid "Your site is running with some customized settings, click the buttons bellow to run with defaults or in bootstrap mode"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:51
+msgid "Are you sure you want to revert to the defaults?"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:51
+msgid "revert to defaults"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:54
+msgid "Are you sure you want to run bootstrap mode?"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:54
+msgid "go bootstrap"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:59
+msgid "Recalculate scores and reputation"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:60
+msgid "This is a heavy operation, are you sure?"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:60
+msgid "Recalculate"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:65
+msgid "Recent activity"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/item.html:12
+msgid "this question has an accepted answer"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/related_tags.html:6
+msgid "Related tags"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:4
+msgid "most recently updated questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:4
+msgid "active"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:5
+msgid "most recently asked questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:5
+msgid "newest"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:6
+msgid "hottest questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:6
+msgid "hottest"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:7
+msgid "most voted questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:7
+msgid "most voted"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:5
+msgid "Found by tags"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:9
+msgid "Search results"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:11
+msgid "Found by title"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:15
+msgid "Unanswered questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:17
+#: forum/skins/default/templates/users/subscriptions.html:74
+msgid "All questions"
+msgstr ""
+
+#: forum/skins/default/templates/sidebar/recent_awards.html:4
+msgid "Recent awards"
+msgstr ""
+
+#: forum/skins/default/templates/sidebar/recent_awards.html:15
+msgid "all awards"
+msgstr ""
+
+#: forum/skins/default/templates/sidebar/recent_tags.html:4
+msgid "Recent tags"
+msgstr ""
+
+#: forum/skins/default/templates/sidebar/recent_tags.html:12
+msgid "popular tags"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:6
+msgid "Edit user profile"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:19
+msgid "edit profile"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:31
+msgid "image associated with your email address"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:31
+#, python-format
+msgid "avatar, see %(gravatar_faq_url)s"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:36
+#: forum/skins/default/templates/users/info.html:52
+msgid "Registered user"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:43
+msgid "Screen Name"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:86
+#: forum/skins/default/templates/users/subscriptions.html:116
+msgid "Update"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:22
+#: forum/skins/default/templates/users/signature.html:6
+#: forum/skins/default/templates/users/users.html:26
+msgid "reputation"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:32
+msgid "Moderate this user"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:44
+msgid "update profile"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:56
+msgid "real name"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:61
+msgid "member for"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:66
+msgid "last seen"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:72
+msgid "user website"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:78
+msgid "location"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:86
+msgid "age"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:87
+msgid "age unit"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:100
+msgid "todays unused votes"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:101
+msgid "votes left"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:13
+#, python-format
+msgid ""
+"\n"
+"                <span class=\"count\">1</span> Question\n"
+"                "
+msgid_plural ""
+"\n"
+"                <span class=\"count\">%(counter)s</span> Questions\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:29
+#, python-format
+msgid ""
+"\n"
+"                <span class=\"count\">1</span> Answer\n"
+"                "
+msgid_plural ""
+"\n"
+"                <span class=\"count\">%(counter)s</span> Answers\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:42
+#, python-format
+msgid "the answer has been voted for %(vote_count)s times"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:42
+msgid "this answer has been selected as correct"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:58
+#, python-format
+msgid ""
+"\n"
+"                    <span class=\"count\">1</span> Vote\n"
+"                "
+msgid_plural ""
+"\n"
+"                    <span class=\"count\">%(cnt)s</span> Votes\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:69
+msgid "thumb up"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:70
+msgid "user has voted up this many times"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:74
+msgid "thumb down"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:75
+msgid "user voted down this many times"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:84
+#, python-format
+msgid ""
+"\n"
+"                    <span class=\"count\">1</span> Tag\n"
+"                "
+msgid_plural ""
+"\n"
+"                    <span class=\"count\">%(counter)s</span> Tags\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:97
+#, python-format
+msgid "see other questions with %(view_user)s's contributions tagged '%(tag_name)s' "
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:112
+#, python-format
+msgid ""
+"\n"
+"            <span class=\"count\">1</span> Badge\n"
+"            "
+msgid_plural ""
+"\n"
+"            <span class=\"count\">%(counter)s</span> Badges\n"
+"            "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/subscriptions.html:8
+msgid "Notifications and subscription settings"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:10
+msgid ""
+"\n"
+"        Here you can decide which types of notifications you wish to receive, and it's frequency.<br />\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:14
+msgid ""
+"\n"
+"        Currently you have notifications enabled. You can always stop all notifications without loosing your settings and restart them afterwards.<br />\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:18
+msgid ""
+"\n"
+"        Currently you have notifications disabled. You can enable them clicking on the <strong>Start notifications</strong> button bellow.<br />\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:28
+msgid "Notify me when:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:32
+msgid "A new member joins"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:36
+msgid "A new question is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:40
+msgid "A new question matching my interesting tags is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:44
+msgid "There's an update on one of my subscriptions"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:52
+msgid "Auto subscribe me to:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:57
+msgid "Questions I ask"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:60
+msgid "Questions I answer"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:63
+msgid "Questions I comment"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:68
+msgid "Questions I view"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:71
+msgid "All questions matching my interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:82
+msgid "On my subscriptions, notify me when:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:87
+msgid "An answer is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:90
+msgid "A comment on one of my posts is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:95
+msgid "A comment is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:98
+msgid "An answer is accepted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:106
+msgid "More:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:111
+msgid "Notify me when someone replys to one of my comments on any post using the <pre>@username</pre> notation"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:118
+msgid "Stop notifications"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:120
+msgid "Start notifications"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:7
+msgid "User profile"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:7
+msgid "overview"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:9
+msgid "recent activity"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:11
+msgid "graph of user reputation"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:12
+msgid "reputation history"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:15 forum/views/users.py:196
+msgid "user vote record"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:15
+msgid "casted votes"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:18
+msgid "questions that user selected as his/her favorite"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:19
+msgid "favorites"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:22
+msgid "email subscription settings"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:23
+msgid "subscriptions"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:6
+#: forum/skins/default/templates/users/users.html:24
+msgid "Users"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:27
+msgid "recent"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:28
+msgid "oldest"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:29
+msgid "by username"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:35
+#, python-format
+msgid "users matching query %(suser)s:"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:39
+msgid "Nothing found."
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:168 forum/templatetags/extra_tags.py:195
+msgid "reputation points"
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:248
+msgid "2 days ago"
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:250
+msgid "yesterday"
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:252
+#, python-format
+msgid "%(hr)d hour ago"
+msgid_plural "%(hr)d hours ago"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/templatetags/extra_tags.py:254
+#, python-format
+msgid "%(min)d min ago"
+msgid_plural "%(min)d mins ago"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/templatetags/node_tags.py:58
+msgid "permanent link"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:58
+msgid "answer permanent link"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:64
+msgid "retag"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:68
+msgid "reopen"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:70
+msgid "close"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:73 forum/views/commands.py:124
+#: forum/views/commands.py:136
+msgid "flag"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:79
+msgid "report as offensive (i.e containing spam, advertising, malicious text, etc.)"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:82
+msgid "delete"
+msgstr ""
+
+#: forum/templatetags/question_list_tags.py:57
+msgid "<strong>Newest</strong> questions are shown first. "
+msgstr ""
+
+#: forum/templatetags/question_list_tags.py:58
+msgid "Questions are sorted by the <strong>time of last update</strong>."
+msgstr ""
+
+#: forum/templatetags/question_list_tags.py:59
+msgid "Questions sorted by <strong>number of responses</strong>."
+msgstr ""
+
+#: forum/templatetags/question_list_tags.py:60
+msgid "Questions are sorted by the <strong>number of votes</strong>."
+msgstr ""
+
+#: forum/templatetags/user_tags.py:58 forum/views/readers.py:293
+#, python-format
+msgid "Revision n. %(rev_number)d"
+msgstr ""
+
+#: forum/utils/forms.py:32
+msgid "this field is required"
+msgstr ""
+
+#: forum/utils/forms.py:47
+msgid "choose a username"
+msgstr ""
+
+#: forum/utils/forms.py:52
+msgid "user name is required"
+msgstr ""
+
+#: forum/utils/forms.py:53
+msgid "sorry, this name is taken, please choose another"
+msgstr ""
+
+#: forum/utils/forms.py:54
+msgid "sorry, this name is not allowed, please choose another"
+msgstr ""
+
+#: forum/utils/forms.py:55
+msgid "sorry, there is no user with this name"
+msgstr ""
+
+#: forum/utils/forms.py:56
+msgid "sorry, we have a serious error - user name is taken by several users"
+msgstr ""
+
+#: forum/utils/forms.py:57
+msgid "user name can only consist of letters, empty space and underscore"
+msgstr ""
+
+#: forum/utils/forms.py:105
+msgid "your email address"
+msgstr ""
+
+#: forum/utils/forms.py:106
+msgid "email address is required"
+msgstr ""
+
+#: forum/utils/forms.py:108
+msgid "this email is already used by someone else, please choose another"
+msgstr ""
+
+#: forum/utils/forms.py:133
+msgid "choose password"
+msgstr ""
+
+#: forum/utils/forms.py:134
+msgid "password is required"
+msgstr ""
+
+#: forum/utils/forms.py:137
+msgid "retype password"
+msgstr ""
+
+#: forum/utils/forms.py:138
+msgid "please, retype your password"
+msgstr ""
+
+#: forum/utils/forms.py:139
+msgid "sorry, entered passwords did not match, please try again"
+msgstr ""
+
+#: forum/views/admin.py:47
+#, python-format
+msgid "'%s' settings saved succesfully"
+msgstr ""
+
+#: forum/views/admin.py:141
+msgid "Bootstrap mode enabled"
+msgstr ""
+
+#: forum/views/admin.py:155
+msgid "All values reverted to defaults"
+msgstr ""
+
+#: forum/views/admin.py:171
+msgid "All values recalculated"
+msgstr ""
+
+#: forum/views/auth.py:103 forum/views/auth.py:112
+msgid "Sorry, these login credentials belong to anoother user. Plese terminate your current session and try again."
+msgstr ""
+
+#: forum/views/auth.py:105
+msgid "You are already logged in with that user."
+msgstr ""
+
+#: forum/views/auth.py:110
+msgid "These login credentials are already associated with your account."
+msgstr ""
+
+#: forum/views/auth.py:116
+msgid "The new credentials are now associated with your account"
+msgstr ""
+
+#: forum/views/auth.py:157
+msgid "Oops, something went wrong in the middle of this process. Please try again."
+msgstr ""
+
+#: forum/views/auth.py:219
+msgid "Temporary login link"
+msgstr ""
+
+#: forum/views/auth.py:224
+msgid "An email has been sent with your temporary login key"
+msgstr ""
+
+#: forum/views/auth.py:239
+msgid "You are logged in with a temporary access key, please take the time to fix your issue with authentication."
+msgstr ""
+
+#: forum/views/auth.py:245
+msgid "Email Validation"
+msgstr ""
+
+#: forum/views/auth.py:256
+msgid "Thank you, your email is now validated."
+msgstr ""
+
+#: forum/views/auth.py:280
+msgid "Your password was changed"
+msgstr ""
+
+#: forum/views/auth.py:282
+msgid "New password set"
+msgstr ""
+
+#: forum/views/auth.py:315
+#, python-format
+msgid "You removed the association with %s"
+msgstr ""
+
+#: forum/views/auth.py:353
+#, python-format
+msgid "Welcome back %s, you are now logged in"
+msgstr ""
+
+#: forum/views/commands.py:20
+#, python-format
+msgid ""
+"\n"
+"            Sorry, but you don't have enough reputation points to %(action)s.<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:29
+#, python-format
+msgid ""
+"\n"
+"            Sorry but you cannot %(action)s your own post.<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:38
+#, python-format
+msgid ""
+"\n"
+"            Sorry but anonymous users cannot %(action)s.<br />\n"
+"            Please login or create an account <a href'%(signin_url)s'>here</a>.\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:47
+#, python-format
+msgid ""
+"\n"
+"            Sorry, but you don't have enough %(action)s left for today..<br />\n"
+"            The limit is %(limit)s per day..<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:57
+#, python-format
+msgid ""
+"\n"
+"            Sorry, but you cannot %(action)s twice the same post.<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:71 forum/views/commands.py:74
+#: forum/views/commands.py:111
+msgid "vote"
+msgid_plural "votes"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/views/commands.py:89
+#, python-format
+msgid "Sorry but you cannot cancel a vote after %(ndays)d %(tdays)s from the original vote"
+msgstr ""
+
+#: forum/views/commands.py:90
+msgid "day"
+msgid_plural "days"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/views/commands.py:110
+#, python-format
+msgid "You have %(nvotes)s %(tvotes)s left today."
+msgstr ""
+
+#: forum/views/commands.py:121 forum/views/commands.py:127
+msgid "flag posts"
+msgstr ""
+
+#: forum/views/commands.py:132
+msgid "flags"
+msgstr ""
+
+#: forum/views/commands.py:149 forum/views/commands.py:155
+msgid "like comments"
+msgstr ""
+
+#: forum/views/commands.py:152
+msgid "like"
+msgstr ""
+
+#: forum/views/commands.py:179 forum/views/commands.py:182
+msgid "delete comments"
+msgstr ""
+
+#: forum/views/commands.py:197
+msgid "mark a question as favorite"
+msgstr ""
+
+#: forum/views/commands.py:221 forum/views/commands.py:233
+msgid "comment"
+msgstr ""
+
+#: forum/views/commands.py:224 forum/views/commands.py:351
+msgid "Invalid request"
+msgstr ""
+
+#: forum/views/commands.py:230
+msgid "edit comments"
+msgstr ""
+
+#: forum/views/commands.py:240
+msgid "Comment is empty"
+msgstr ""
+
+#: forum/views/commands.py:265
+msgid "accept answers"
+msgstr ""
+
+#: forum/views/commands.py:271
+msgid "Sorry but only the question author can accept an answer"
+msgstr ""
+
+#: forum/views/commands.py:295 forum/views/commands.py:298
+msgid "delete posts"
+msgstr ""
+
+#: forum/views/meta.py:43
+#, python-format
+msgid "Feedback message from %(site_name)s"
+msgstr ""
+
+#: forum/views/meta.py:46
+msgid "Thanks for the feedback!"
+msgstr ""
+
+#: forum/views/meta.py:53
+msgid "We look forward to hearing your feedback! Please, give it next time :)"
+msgstr ""
+
+#: forum/views/readers.py:64
+msgid "Open questions without an accepted answer"
+msgstr ""
+
+#: forum/views/readers.py:73
+#, python-format
+msgid "Questions tagged <span class=\"tag\">%(tag)s</span>"
+msgstr ""
+
+#: forum/views/readers.py:131
+#, python-format
+msgid "questions matching '%(keywords)s'"
+msgstr ""
+
+#: forum/views/users.py:152
+msgid "user profile"
+msgstr ""
+
+#: forum/views/users.py:152
+msgid "user profile overview"
+msgstr ""
+
+#: forum/views/users.py:186
+msgid "recent user activity"
+msgstr ""
+
+#: forum/views/users.py:186
+msgid "profile - recent activity"
+msgstr ""
+
+#: forum/views/users.py:196
+msgid "profile - votes"
+msgstr ""
+
+#: forum/views/users.py:203
+msgid "user reputation in the community"
+msgstr ""
+
+#: forum/views/users.py:203
+msgid "profile - user reputation"
+msgstr ""
+
+#: forum/views/users.py:214
+msgid "favorite questions"
+msgstr ""
+
+#: forum/views/users.py:214
+msgid "profile - favorite questions"
+msgstr ""
+
+#: forum/views/users.py:220
+msgid "subscription settings"
+msgstr ""
+
+#: forum/views/users.py:220
+msgid "profile - subscriptions"
+msgstr ""
+
+#: forum/views/users.py:230
+msgid "Notifications are now enabled"
+msgstr ""
+
+#: forum/views/users.py:232
+msgid "Notifications are now disabled"
+msgstr ""
+
+#: forum/views/users.py:239
+msgid "New subscription settings are now saved"
+msgstr ""
+
+#: forum/views/writers.py:68
+msgid "uploading images is limited to users with >60 reputation points"
+msgstr ""
+
+#: forum/views/writers.py:70
+msgid "allowed file types are 'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'"
+msgstr ""
+
+#: forum/views/writers.py:72
+#, python-format
+msgid "maximum upload file size is %sM"
+msgstr ""
+
+#: forum/views/writers.py:74
+#, python-format
+msgid "Error uploading file. Please contact the site administrator. Thank you. %s"
+msgstr ""
+
+#: forum/views/writers.py:85
+msgid "Initial revision"
+msgstr ""
+
+#: forum/views/writers.py:143
+msgid "Retag"
+msgstr ""
+
+#: forum_modules/books/urls.py:7 forum_modules/books/urls.py:8
+#: forum_modules/books/urls.py:9
+msgid "books/"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:17
+#: forum_modules/default_badges/badges.py:24
+#: forum_modules/default_badges/badges.py:31
+#, python-format
+msgid "Asked a question with %s views"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:39
+#: forum_modules/default_badges/badges.py:53
+#: forum_modules/default_badges/badges.py:67
+#, python-format
+msgid "Answer voted up %s times"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:46
+#: forum_modules/default_badges/badges.py:60
+#: forum_modules/default_badges/badges.py:74
+#, python-format
+msgid "Question voted up %s times"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:82
+#: forum_modules/default_badges/badges.py:89
+#, python-format
+msgid "Question favorited by %s users"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:97
+#, python-format
+msgid "Deleted own post with score of %s or higher"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:108
+#, python-format
+msgid "Deleted own post with score of %s or lower"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:120
+msgid "First flagged post"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:127
+msgid "First down vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:134
+msgid "First retag"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:141
+msgid "First up vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:148
+msgid "First edit"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:155
+msgid "First accepted answer on your own question"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:162
+msgid "Completed all user profile fields"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:169
+msgid "First rollback"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:177
+#, python-format
+msgid "Voted %s times"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:184
+#, python-format
+msgid "Left %s comments"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:192
+#, python-format
+msgid "Answered your own question with at least %s up votes"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:205
+msgid "Strunk & White"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:206
+#, python-format
+msgid "Edited %s entries"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:217
+msgid "Asked first question with at least one up vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:228
+msgid "Answered first question with at least one up vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:260
+#, python-format
+msgid "First answer was accepted with at least %s up votes"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:271
+#, python-format
+msgid "Accepted answer and voted up %s times"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:282
+#, python-format
+msgid "Answered a question more than %(dif_days)s days later with at least %(up_votes)s votes"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:295
+#, python-format
+msgid "Created a tag used by %s questions"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:6
+msgid "Popular Question views"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:7
+msgid ""
+"\n"
+"Number of question views required to award a Popular Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:12
+msgid "Notable Question views"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:13
+msgid ""
+"\n"
+"Number of question views required to award a Notable Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:18
+msgid "Famous Question views"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:19
+msgid ""
+"\n"
+"Number of question views required to award a Famous Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:24
+msgid "Nice Answer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:25
+msgid ""
+"\n"
+"Number of up votes required to award a Nice Answer badge to the answer author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:30
+msgid "Nice Question up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:31
+msgid ""
+"\n"
+"Number of up votes required to award a Nice Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:36
+msgid "Good Answer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:37
+msgid ""
+"\n"
+"Number of up votes required to award a Good Answer badge to the answer author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:42
+msgid "Good Question up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:43
+msgid ""
+"\n"
+"Number of up votes required to award a Good Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:48
+msgid "Great Answer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:49
+msgid ""
+"\n"
+"Number of up votes required to award a Great Answer badge to the answer author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:54
+msgid "Great Question up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:55
+msgid ""
+"\n"
+"Number of up votes required to award a Great Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:60
+msgid "Favorite Question favorite count"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:61
+msgid ""
+"\n"
+"How many times a question needs to be favorited by other users to award a Favorite Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:66
+msgid "Stellar Question favorite count"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:67
+msgid ""
+"\n"
+"How many times a question needs to be favorited by other users to award a Stellar Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:72
+msgid "Disciplined minimum score"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:73
+msgid ""
+"\n"
+"Minimum score a question needs to have to award the Disciplined badge to an author of a question who deletes it.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:78
+msgid "Peer Pressure maximum score"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:79
+msgid ""
+"\n"
+"Maximum score a question needs to have to award the Peer Pressure badge to an author of a question who deletes it.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:84
+msgid "Civic Duty votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:85
+msgid ""
+"\n"
+"Number of votes an user needs to cast to be awarded the Civic Duty badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:90
+msgid "Pundit number of comments"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:91
+msgid ""
+"\n"
+"Number of comments an user needs to post to be awarded the Pundit badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:96
+msgid "Self Learner up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:97
+msgid ""
+"\n"
+"Number of up votes an answer from the question author needs to have for the author to be awarded the Self Learner badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:102
+msgid "Strunk and White updates"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:103
+msgid ""
+"\n"
+"Number of question or answer updates an user needs to make to be awarded the Strunk & White badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:108
+msgid "Enlightened up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:109
+msgid ""
+"\n"
+"Number of up votes an accepted answer needs to have for the author to be awarded the Enlightened badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:114
+msgid "Guru up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:115
+msgid ""
+"\n"
+"Number of up votes an accepted answer needs to have for the author to be awarded the Guru badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:120
+msgid "Necromancer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:121
+msgid ""
+"\n"
+"Number of up votes an answer needs to have for the author to be awarded the Necromancer badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:126
+msgid "Necromancer difference in days"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:127
+msgid ""
+"\n"
+"Difference in days betwen the posted date of a question and an answer for the answer author to be awarded the Necromancer badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:132
+msgid "Taxonomist usage count"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:133
+msgid ""
+"\n"
+"How many usages a tag needs to have for the tag creator to be awarded the Taxonomist badge. \n"
+msgstr ""
+
+#: forum_modules/facebookauth/authentication.py:31
+msgid "Sorry, your Facebook session has expired, please try again"
+msgstr ""
+
+#: forum_modules/facebookauth/authentication.py:33
+msgid "The authentication with Facebook connect failed due to an invalid signature"
+msgstr ""
+
+#: forum_modules/facebookauth/authentication.py:35
+msgid "The authentication with Facebook connect failed, cannot find authentication tokens"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:75
+msgid "Please enter valid username and password (both are case-sensitive)."
+msgstr ""
+
+#: forum_modules/localauth/forms.py:79
+msgid "This account is inactive."
+msgstr ""
+
+#: forum_modules/localauth/forms.py:81
+msgid "Login failed."
+msgstr ""
+
+#: forum_modules/localauth/forms.py:85
+msgid "This user is not a valid user"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:88
+msgid "Please enter username and password"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:90
+msgid "Please enter your password"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:92
+msgid "Please enter user name"
+msgstr ""
+
+#: forum_modules/localauth/urls.py:7
+msgid "local/"
+msgstr ""
+
+#: forum_modules/localauth/views.py:33
+msgid "A validation email has been sent to your email address. "
+msgstr ""
+
+#: forum_modules/oauthauth/consumer.py:33
+msgid "Error, the oauth token is not on the server"
+msgstr ""
+
+#: forum_modules/oauthauth/consumer.py:38
+msgid "Something went wrong! Auth tokens do not match"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:40
+msgid "Sorry, but your input is not a valid OpenId"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:92
+msgid "The OpenId authentication request was canceled"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:94
+msgid "The OpenId authentication failed: "
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:96
+msgid "Setup needed"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:98
+msgid "The OpenId authentication failed with an unknown status: "
+msgstr ""
+
+#: forum_modules/openidauth/templates/openidurl.html:7
+msgid "Enter your OpenId Url"
+msgstr ""
+
+#: forum_modules/project_badges/badges.py:9
+#, python-format
+msgid "Got %s upvotes in a question tagged with \"bug\""
+msgstr ""
+
+#: forum_modules/recaptcha/formfield.py:20
+msgid "Invalid captcha"
+msgstr ""
+
+#: forum_modules/sximporter/importer.py:39
+#, python-format
+msgid "Unknown user %(number)d"
+msgstr ""
+
+#: forum_modules/sximporter/urls.py:8
+msgid "sximporter/"
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:7
+msgid "SX Importer"
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:10
+msgid "Welcome to Stack Exchange dump importer."
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:16
+msgid "Your user id in stack exchange"
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:20
+msgid "Merge users with same user name and email"
+msgstr ""
+
+#: locale/phrases.py:1
+msgid "Test Phrase 1"
+msgstr ""
+
+#: locale/phrases.py:2
+msgid "Test Phrase 2"
+msgstr ""
+
+#: locale/phrases.py:3
+msgid "Test Phrase 3"
+msgstr ""
+
+#: locale/phrases.py:4
+msgid "Test Phrase n"
+msgstr ""
diff --git a/forum/modules/template_loader.py/locale/fr/LC_MESSAGES/django.mo b/forum/modules/template_loader.py/locale/fr/LC_MESSAGES/django.mo
new file mode 100644 (file)
index 0000000..345109f
Binary files /dev/null and b/forum/modules/template_loader.py/locale/fr/LC_MESSAGES/django.mo differ
diff --git a/forum/modules/template_loader.py/locale/fr/LC_MESSAGES/django.po b/forum/modules/template_loader.py/locale/fr/LC_MESSAGES/django.po
new file mode 100644 (file)
index 0000000..7a76e84
--- /dev/null
@@ -0,0 +1,4446 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-04-28 16:53-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"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: forum/const.py:8
+msgid "duplicate question"
+msgstr ""
+
+#: forum/const.py:9
+msgid "question is off-topic or not relevant"
+msgstr ""
+
+#: forum/const.py:10
+msgid "too subjective and argumentative"
+msgstr ""
+
+#: forum/const.py:11
+msgid "is not an answer to the question"
+msgstr ""
+
+#: forum/const.py:12
+msgid "the question is answered, right answer was accepted"
+msgstr ""
+
+#: forum/const.py:13
+msgid "problem is not reproducible or outdated"
+msgstr ""
+
+#: forum/const.py:14
+msgid "question contains offensive inappropriate, or malicious remarks"
+msgstr ""
+
+#: forum/const.py:15
+msgid "spam or advertising"
+msgstr ""
+
+#: forum/const.py:71 forum/skins/default/templates/osqaadmin/index.html:21
+msgid "question"
+msgstr ""
+
+#: forum/const.py:72 forum/skins/default/templates/book.html:110
+#: forum/skins/default/templates/osqaadmin/index.html:26
+msgid "answer"
+msgstr ""
+
+#: forum/const.py:73
+msgid "commented question"
+msgstr ""
+
+#: forum/const.py:74
+msgid "commented answer"
+msgstr ""
+
+#: forum/const.py:75
+msgid "edited question"
+msgstr ""
+
+#: forum/const.py:76
+msgid "edited answer"
+msgstr ""
+
+#: forum/const.py:77
+msgid "received award"
+msgstr ""
+
+#: forum/const.py:78
+msgid "marked best answer"
+msgstr ""
+
+#: forum/const.py:79
+msgid "upvoted"
+msgstr ""
+
+#: forum/const.py:80
+msgid "downvoted"
+msgstr ""
+
+#: forum/const.py:81
+msgid "upvote canceled"
+msgstr ""
+
+#: forum/const.py:82
+msgid "downvote canceled"
+msgstr ""
+
+#: forum/const.py:83
+msgid "deleted question"
+msgstr ""
+
+#: forum/const.py:84
+msgid "deleted answer"
+msgstr ""
+
+#: forum/const.py:85
+msgid "marked offensive"
+msgstr ""
+
+#: forum/const.py:86
+msgid "updated tags"
+msgstr ""
+
+#: forum/const.py:87
+msgid "selected favorite"
+msgstr ""
+
+#: forum/const.py:88
+msgid "completed user profile"
+msgstr ""
+
+#: forum/const.py:89
+msgid "email update sent to user"
+msgstr ""
+
+#: forum/const.py:93
+msgid "question_answered"
+msgstr ""
+
+#: forum/const.py:94
+msgid "question_commented"
+msgstr ""
+
+#: forum/const.py:95
+msgid "answer_commented"
+msgstr ""
+
+#: forum/const.py:96
+msgid "answer_accepted"
+msgstr ""
+
+#: forum/const.py:100
+msgid "[closed]"
+msgstr ""
+
+#: forum/const.py:101
+msgid "[deleted]"
+msgstr ""
+
+#: forum/const.py:102
+msgid "initial version"
+msgstr ""
+
+#: forum/const.py:103
+msgid "retagged"
+msgstr ""
+
+#: forum/const.py:111
+msgid "Instantly"
+msgstr ""
+
+#: forum/const.py:112
+msgid "Daily"
+msgstr ""
+
+#: forum/const.py:113
+msgid "Weekly"
+msgstr ""
+
+#: forum/const.py:114
+msgid "No notifications"
+msgstr ""
+
+#: forum/feed.py:18
+msgid " - "
+msgstr ""
+
+#: forum/feed.py:18
+msgid "latest questions"
+msgstr ""
+
+#: forum/forms.py:21 forum/skins/default/templates/answer_edit_tips.html:35
+#: forum/skins/default/templates/answer_edit_tips.html:39
+#: forum/skins/default/templates/question_edit_tips.html:37
+#: forum/skins/default/templates/question_edit_tips.html:42
+msgid "title"
+msgstr ""
+
+#: forum/forms.py:22
+msgid "please enter a descriptive title for your question"
+msgstr ""
+
+#: forum/forms.py:27
+msgid "title must be > 10 characters"
+msgstr ""
+
+#: forum/forms.py:36
+msgid "content"
+msgstr ""
+
+#: forum/forms.py:42
+msgid "question content must be > 10 characters"
+msgstr ""
+
+#: forum/forms.py:52 forum/skins/default/templates/header.html:31
+#: forum/skins/default/templates/header.html:56
+msgid "tags"
+msgstr ""
+
+#: forum/forms.py:54
+msgid ""
+"Tags are short keywords, with no spaces within. Up to five tags can be used."
+msgstr ""
+
+#: forum/forms.py:61 forum/skins/default/templates/question_retag.html:43
+msgid "tags are required"
+msgstr ""
+
+#: forum/forms.py:67
+msgid "please use 5 tags or less"
+msgstr ""
+
+#: forum/forms.py:72
+msgid "tags must be shorter than 20 characters"
+msgstr ""
+
+#: forum/forms.py:74
+msgid ""
+"please use following characters in tags: letters 'a-z', numbers, and "
+"characters '.-_#'"
+msgstr ""
+
+#: forum/forms.py:84
+#: forum/skins/default/templates/post_contributor_info.html:7
+#: forum/skins/default/templates/question_summary_list_roll.html:26
+#: forum/skins/default/templates/question_summary_list_roll.html:38
+msgid "community wiki"
+msgstr ""
+
+#: forum/forms.py:85
+msgid ""
+"if you choose community wiki option, the question and answer do not generate "
+"points and name of author will not be shown"
+msgstr ""
+
+#: forum/forms.py:101
+msgid "update summary:"
+msgstr ""
+
+#: forum/forms.py:102
+msgid ""
+"enter a brief summary of your revision (e.g. fixed spelling, grammar, "
+"improved style, this field is optional)"
+msgstr ""
+
+#: forum/forms.py:105
+msgid "Automatically accept user's contributions for the email updates"
+msgstr ""
+
+#: forum/forms.py:118
+msgid "Your name:"
+msgstr ""
+
+#: forum/forms.py:119
+msgid "Email (not shared with anyone):"
+msgstr ""
+
+#: forum/forms.py:120
+msgid "Your message:"
+msgstr ""
+
+#: forum/forms.py:202
+msgid "this email does not have to be linked to gravatar"
+msgstr ""
+
+#: forum/forms.py:204
+msgid "Screen name"
+msgstr ""
+
+#: forum/forms.py:205
+msgid "Real name"
+msgstr ""
+
+#: forum/forms.py:206
+msgid "Website"
+msgstr ""
+
+#: forum/forms.py:207
+msgid "Location"
+msgstr ""
+
+#: forum/forms.py:208
+msgid "Date of birth"
+msgstr ""
+
+#: forum/forms.py:208
+msgid "will not be shown, used to calculate age, format: YYYY-MM-DD"
+msgstr ""
+
+#: forum/forms.py:209 forum/skins/default/templates/account_settings.html:21
+msgid "Profile"
+msgstr ""
+
+#: forum/forms.py:240 forum/forms.py:241
+msgid "this email has already been registered, please use another one"
+msgstr ""
+
+#: forum/subscriptions.py:41
+#, python-format
+msgid "New question on %(app_name)s"
+msgstr ""
+
+#: forum/subscriptions.py:73
+#, python-format
+msgid "New answer to '%(question_title)s'"
+msgstr ""
+
+#: forum/subscriptions.py:112
+#, python-format
+msgid "New comment on %(question_title)s"
+msgstr ""
+
+#: forum/subscriptions.py:136
+#, python-format
+msgid "An answer to '%(question_title)s' was accepted"
+msgstr ""
+
+#: forum/subscriptions.py:156
+#, python-format
+msgid "%(username)s is a new member on %(app_name)s"
+msgstr ""
+
+#: forum/urls.py:44
+msgid "upfiles/"
+msgstr ""
+
+#: forum/urls.py:49
+msgid "about/"
+msgstr ""
+
+#: forum/urls.py:50
+msgid "faq/"
+msgstr ""
+
+#: forum/urls.py:51
+msgid "privacy/"
+msgstr ""
+
+#: forum/urls.py:52
+msgid "logout/"
+msgstr ""
+
+#: forum/urls.py:53 forum/urls.py:54
+msgid "answers/"
+msgstr ""
+
+#: forum/urls.py:53 forum/urls.py:58 forum/urls.py:98
+#: forum/skins/default/templates/users/info.html:44
+msgid "edit/"
+msgstr ""
+
+#: forum/urls.py:54 forum/urls.py:74
+msgid "revisions/"
+msgstr ""
+
+#: forum/urls.py:55 forum/urls.py:56 forum/urls.py:57 forum/urls.py:58
+#: forum/urls.py:59 forum/urls.py:60 forum/urls.py:61 forum/urls.py:74
+msgid "questions/"
+msgstr ""
+
+#: forum/urls.py:56 forum_modules/books/urls.py:8
+msgid "ask/"
+msgstr ""
+
+#: forum/urls.py:57
+msgid "unanswered/"
+msgstr ""
+
+#: forum/urls.py:59
+msgid "close/"
+msgstr ""
+
+#: forum/urls.py:60
+msgid "reopen/"
+msgstr ""
+
+#: forum/urls.py:61
+msgid "answer/"
+msgstr ""
+
+#: forum/urls.py:63
+msgid "vote/"
+msgstr ""
+
+#: forum/urls.py:64
+msgid "like_comment/"
+msgstr ""
+
+#: forum/urls.py:65
+msgid "comment/"
+msgstr ""
+
+#: forum/urls.py:66
+msgid "delete_comment/"
+msgstr ""
+
+#: forum/urls.py:67
+msgid "accept_answer/"
+msgstr ""
+
+#: forum/urls.py:68
+msgid "mark_favorite/"
+msgstr ""
+
+#: forum/urls.py:69
+msgid "flag/"
+msgstr ""
+
+#: forum/urls.py:70
+msgid "delete/"
+msgstr ""
+
+#: forum/urls.py:71
+msgid "subscribe/"
+msgstr ""
+
+#: forum/urls.py:72
+msgid "matching_tags/"
+msgstr ""
+
+#: forum/urls.py:75
+msgid "command/"
+msgstr ""
+
+#: forum/urls.py:78
+msgid "question/"
+msgstr ""
+
+#: forum/urls.py:79 forum/urls.py:80
+msgid "tags/"
+msgstr ""
+
+#: forum/urls.py:82 forum/urls.py:86
+msgid "mark-tag/"
+msgstr ""
+
+#: forum/urls.py:82
+msgid "interesting/"
+msgstr ""
+
+#: forum/urls.py:86
+msgid "ignored/"
+msgstr ""
+
+#: forum/urls.py:90
+msgid "unmark-tag/"
+msgstr ""
+
+#: forum/urls.py:96 forum/urls.py:98 forum/urls.py:100 forum/urls.py:101
+#: forum/urls.py:102 forum/urls.py:103 forum/urls.py:104 forum/urls.py:105
+#: forum/models/user.py:124
+msgid "users/"
+msgstr ""
+
+#: forum/urls.py:97
+msgid "moderate-user/"
+msgstr ""
+
+#: forum/urls.py:100
+msgid "subscriptions/"
+msgstr ""
+
+#: forum/urls.py:101
+msgid "favorites/"
+msgstr ""
+
+#: forum/urls.py:102
+msgid "reputation/"
+msgstr ""
+
+#: forum/urls.py:103
+msgid "votes/"
+msgstr ""
+
+#: forum/urls.py:104
+msgid "recent/"
+msgstr ""
+
+#: forum/urls.py:107 forum/urls.py:108
+msgid "badges/"
+msgstr ""
+
+#: forum/urls.py:109
+msgid "messages/"
+msgstr ""
+
+#: forum/urls.py:109
+msgid "markread/"
+msgstr ""
+
+#: forum/urls.py:111
+msgid "nimda/"
+msgstr ""
+
+#: forum/urls.py:113
+msgid "upload/"
+msgstr ""
+
+#: forum/urls.py:114
+msgid "search/"
+msgstr ""
+
+#: forum/urls.py:115
+msgid "feedback/"
+msgstr ""
+
+#: forum/urls.py:119 forum/urls.py:120 forum/urls.py:121 forum/urls.py:122
+#: forum/urls.py:123 forum/urls.py:124 forum/urls.py:125 forum/urls.py:126
+#: forum/urls.py:127 forum/urls.py:128 forum/urls.py:129 forum/urls.py:130
+#: forum_modules/localauth/urls.py:7
+msgid "account/"
+msgstr ""
+
+#: forum/urls.py:119 forum/urls.py:121 forum/urls.py:122
+msgid "signin/"
+msgstr ""
+
+#: forum/urls.py:120
+msgid "signout/"
+msgstr ""
+
+#: forum/urls.py:123
+msgid "done/"
+msgstr ""
+
+#: forum/urls.py:124 forum_modules/localauth/urls.py:7
+msgid "register/"
+msgstr ""
+
+#: forum/urls.py:125
+msgid "validate/"
+msgstr ""
+
+#: forum/urls.py:126 forum/urls.py:127
+msgid "tempsignin/"
+msgstr ""
+
+#: forum/urls.py:128
+msgid "authsettings/"
+msgstr ""
+
+#: forum/urls.py:129 forum/urls.py:130
+msgid "providers/"
+msgstr ""
+
+#: forum/urls.py:129
+msgid "remove/"
+msgstr ""
+
+#: forum/urls.py:130
+msgid "add/"
+msgstr ""
+
+#: forum/urls.py:133 forum/urls.py:134 forum/urls.py:135 forum/urls.py:136
+#: forum/urls.py:137 forum_modules/sximporter/urls.py:8
+msgid "admin/"
+msgstr ""
+
+#: forum/urls.py:134
+msgid "denormalize/"
+msgstr ""
+
+#: forum/urls.py:135
+msgid "go_bootstrap/"
+msgstr ""
+
+#: forum/urls.py:136
+msgid "go_defaults/"
+msgstr ""
+
+#: forum/authentication/forms.py:21
+msgid "Your account email"
+msgstr ""
+
+#: forum/authentication/forms.py:23
+msgid "You cannot leave this field blank"
+msgstr ""
+
+#: forum/authentication/forms.py:24 forum/utils/forms.py:107
+msgid "please enter a valid email address"
+msgstr ""
+
+#: forum/authentication/forms.py:32
+msgid "Sorry, but this email is not on our database."
+msgstr ""
+
+#: forum/authentication/forms.py:40
+msgid "okay, let's try!"
+msgstr ""
+
+#: forum/authentication/forms.py:41
+msgid "no OSQA community email please, thanks"
+msgstr ""
+
+#: forum/authentication/forms.py:44
+msgid "please choose one of the options above"
+msgstr ""
+
+#: forum/authentication/forms.py:51
+msgid "Current password"
+msgstr ""
+
+#: forum/authentication/forms.py:62
+msgid ""
+"Old password is incorrect.                     Please enter the correct "
+"password."
+msgstr ""
+
+#: forum/management/commands/send_email_alerts.py:56
+msgid "Daily digest"
+msgstr ""
+
+#: forum/middleware/anon_user.py:34
+#, python-format
+msgid "First time here? Check out the <a href=\"%s\">FAQ</a>!"
+msgstr ""
+
+#: forum/models/question.py:30
+msgid "[closed] "
+msgstr ""
+
+#: forum/models/question.py:33
+msgid "[deleted] "
+msgstr ""
+
+#: forum/models/repute.py:13 forum/skins/default/templates/badges.html:53
+msgid "gold"
+msgstr ""
+
+#: forum/models/repute.py:14 forum/skins/default/templates/badges.html:61
+msgid "silver"
+msgstr ""
+
+#: forum/models/repute.py:15 forum/skins/default/templates/badges.html:68
+msgid "bronze"
+msgstr ""
+
+#: forum/models/tag.py:28
+msgid "interesting"
+msgstr ""
+
+#: forum/models/tag.py:28
+msgid "ignored"
+msgstr ""
+
+#: forum/models/user.py:255
+#: forum/skins/default/templates/post_contributor_info.html:19
+msgid "asked"
+msgstr ""
+
+#: forum/models/user.py:257
+#: forum/skins/default/templates/post_contributor_info.html:22
+msgid "answered"
+msgstr ""
+
+#: forum/models/user.py:259
+msgid "marked an answer"
+msgstr ""
+
+#: forum/models/user.py:261
+msgid "edited a question"
+msgstr ""
+
+#: forum/models/user.py:263
+msgid "commented a question"
+msgstr ""
+
+#: forum/models/user.py:265
+msgid "commented an answer"
+msgstr ""
+
+#: forum/models/user.py:267
+msgid "edited an answer"
+msgstr ""
+
+#: forum/models/user.py:269
+msgid "received badge"
+msgstr ""
+
+#: forum/settings/__init__.py:20
+msgid "Badges config"
+msgstr ""
+
+#: forum/settings/__init__.py:20
+msgid "Configure badges on your OSQA site."
+msgstr ""
+
+#: forum/settings/basic.py:9
+msgid "Basic Settings"
+msgstr ""
+
+#: forum/settings/basic.py:9
+msgid "The basic settings for your application"
+msgstr ""
+
+#: forum/settings/basic.py:12
+msgid "Application logo"
+msgstr ""
+
+#: forum/settings/basic.py:13
+msgid "Your site main logo."
+msgstr ""
+
+#: forum/settings/basic.py:17
+msgid "Favicon"
+msgstr ""
+
+#: forum/settings/basic.py:18
+msgid "Your site favicon."
+msgstr ""
+
+#: forum/settings/basic.py:22
+msgid "Application title"
+msgstr ""
+
+#: forum/settings/basic.py:23
+msgid "The title of your application that will show in the browsers title bar"
+msgstr ""
+
+#: forum/settings/basic.py:26
+msgid "Application short name"
+msgstr ""
+
+#: forum/settings/basic.py:30
+msgid "Application keywords"
+msgstr ""
+
+#: forum/settings/basic.py:31
+msgid "The meta keywords that will be available through the HTML meta tags."
+msgstr ""
+
+#: forum/settings/basic.py:34
+msgid "Application description"
+msgstr ""
+
+#: forum/settings/basic.py:35
+msgid "The description of your application"
+msgstr ""
+
+#: forum/settings/basic.py:39
+msgid "Application intro"
+msgstr ""
+
+#: forum/settings/basic.py:40
+msgid ""
+"The introductory page that is visible in the sidebar for anonymous users."
+msgstr ""
+
+#: forum/settings/basic.py:44
+msgid "Copyright notice"
+msgstr ""
+
+#: forum/settings/basic.py:45
+msgid "The copyright notice visible at the footer of your page."
+msgstr ""
+
+#: forum/settings/basic.py:48
+msgid "Maximum length of comment"
+msgstr ""
+
+#: forum/settings/basic.py:49
+msgid "The maximum length a user can enter for a comment."
+msgstr ""
+
+#: forum/settings/email.py:5
+msgid "Email Settings"
+msgstr ""
+
+#: forum/settings/email.py:5
+msgid "Email server and other email related settings."
+msgstr ""
+
+#: forum/settings/email.py:8
+msgid "Email Server"
+msgstr ""
+
+#: forum/settings/email.py:9
+msgid "The SMTP server through which your application will be sending emails."
+msgstr ""
+
+#: forum/settings/email.py:13
+msgid "Email Port"
+msgstr ""
+
+#: forum/settings/email.py:14
+msgid ""
+"The port on which your SMTP server is listening to. Usually this is 25, but "
+"can be something else."
+msgstr ""
+
+#: forum/settings/email.py:18
+msgid "Email User"
+msgstr ""
+
+#: forum/settings/email.py:19
+msgid "The username for your SMTP connection."
+msgstr ""
+
+#: forum/settings/email.py:23
+msgid "Email Password"
+msgstr ""
+
+#: forum/settings/email.py:24
+msgid "The password for your SMTP connection."
+msgstr ""
+
+#: forum/settings/email.py:29
+msgid "Use TLS"
+msgstr ""
+
+#: forum/settings/email.py:30
+msgid "Does your SMTP server usFes TLS for authentication."
+msgstr ""
+
+#: forum/settings/email.py:34
+msgid "Site 'from' email address"
+msgstr ""
+
+#: forum/settings/email.py:35
+msgid ""
+"The address that will show up on the 'from' field on emails sent by your "
+"website."
+msgstr ""
+
+#: forum/settings/email.py:39
+msgid "Email subject prefix"
+msgstr ""
+
+#: forum/settings/email.py:40
+msgid ""
+"Every email sent through your website will have the subject prefixed by this "
+"string. It's usually a good idea to have such a prefix so your users can "
+"easilly set up a filter on their email clients."
+msgstr ""
+
+#: forum/settings/extkeys.py:4
+msgid "External Keys"
+msgstr ""
+
+#: forum/settings/extkeys.py:4
+msgid ""
+"Keys for various external providers that your application may optionally use."
+msgstr ""
+
+#: forum/settings/extkeys.py:7
+msgid "Google sitemap code"
+msgstr ""
+
+#: forum/settings/extkeys.py:8
+msgid ""
+"This is the code you get when you register your site at <a href='https://www."
+"google.com/webmasters/tools/'>Google webmaster central</a>."
+msgstr ""
+
+#: forum/settings/extkeys.py:12
+msgid "Google analytics key"
+msgstr ""
+
+#: forum/settings/extkeys.py:13
+msgid ""
+"Your Google analytics key. You can get one at the <a href='http://www.google."
+"com/analytics/'>Google analytics official website</a>"
+msgstr ""
+
+#: forum/settings/forms.py:40
+msgid "Change this:"
+msgstr ""
+
+#: forum/settings/minrep.py:4
+msgid "Minimum reputation config"
+msgstr ""
+
+#: forum/settings/minrep.py:4
+msgid ""
+"Configure the minimum reputation required to perform certain actions on your "
+"site."
+msgstr ""
+
+#: forum/settings/minrep.py:7
+msgid "Minimum reputation to vote up"
+msgstr ""
+
+#: forum/settings/minrep.py:8
+msgid "The minimum reputation an user must have to be allowed to vote up."
+msgstr ""
+
+#: forum/settings/minrep.py:11
+msgid "Minimum reputation to vote down"
+msgstr ""
+
+#: forum/settings/minrep.py:12
+msgid "The minimum reputation an user must have to be allowed to vote down."
+msgstr ""
+
+#: forum/settings/minrep.py:15
+msgid "Minimum reputation to flag a post"
+msgstr ""
+
+#: forum/settings/minrep.py:16
+msgid "The minimum reputation an user must have to be allowed to flag a post."
+msgstr ""
+
+#: forum/settings/minrep.py:19
+msgid "Minimum reputation to comment"
+msgstr ""
+
+#: forum/settings/minrep.py:20
+msgid ""
+"The minimum reputation an user must have to be allowed to comment a post."
+msgstr ""
+
+#: forum/settings/minrep.py:23
+msgid "Minimum reputation to like a comment"
+msgstr ""
+
+#: forum/settings/minrep.py:24
+msgid ""
+"The minimum reputation an user must have to be allowed to \"like\" a comment."
+msgstr ""
+
+#: forum/settings/minrep.py:27
+msgid "Minimum reputation to upload"
+msgstr ""
+
+#: forum/settings/minrep.py:28
+msgid ""
+"The minimum reputation an user must have to be allowed to upload a file."
+msgstr ""
+
+#: forum/settings/minrep.py:31
+msgid "Minimum reputation to close own question"
+msgstr ""
+
+#: forum/settings/minrep.py:32
+msgid ""
+"The minimum reputation an user must have to be allowed to close his own "
+"question."
+msgstr ""
+
+#: forum/settings/minrep.py:35
+msgid "Minimum reputation to reopen own question"
+msgstr ""
+
+#: forum/settings/minrep.py:36
+msgid ""
+"The minimum reputation an user must have to be allowed to reopen his own "
+"question."
+msgstr ""
+
+#: forum/settings/minrep.py:39
+msgid "Minimum reputation to retag others questions"
+msgstr ""
+
+#: forum/settings/minrep.py:40
+msgid ""
+"The minimum reputation an user must have to be allowed to retag others "
+"questions."
+msgstr ""
+
+#: forum/settings/minrep.py:43
+msgid "Minimum reputation to edit wiki posts"
+msgstr ""
+
+#: forum/settings/minrep.py:44
+msgid ""
+"The minimum reputation an user must have to be allowed to edit community "
+"wiki posts."
+msgstr ""
+
+#: forum/settings/minrep.py:47
+msgid "Minimum reputation to edit others posts"
+msgstr ""
+
+#: forum/settings/minrep.py:48
+msgid ""
+"The minimum reputation an user must have to be allowed to edit others posts."
+msgstr ""
+
+#: forum/settings/minrep.py:51
+msgid "Minimum reputation to close others posts"
+msgstr ""
+
+#: forum/settings/minrep.py:52
+msgid ""
+"The minimum reputation an user must have to be allowed to close others posts."
+msgstr ""
+
+#: forum/settings/minrep.py:55
+msgid "Minimum reputation to delete comments"
+msgstr ""
+
+#: forum/settings/minrep.py:56
+msgid ""
+"The minimum reputation an user must have to be allowed to delete comments."
+msgstr ""
+
+#: forum/settings/minrep.py:59
+msgid "Minimum reputation to view offensive flags"
+msgstr ""
+
+#: forum/settings/minrep.py:60
+msgid "The minimum reputation an user must have to view offensive flags."
+msgstr ""
+
+#: forum/settings/repgain.py:4
+msgid "Reputation gains and losses config"
+msgstr ""
+
+#: forum/settings/repgain.py:4
+msgid ""
+"Configure the reputation points a user may gain or lose upon certain actions."
+msgstr ""
+
+#: forum/settings/repgain.py:7
+msgid "Initial reputation"
+msgstr ""
+
+#: forum/settings/repgain.py:8
+msgid "The initial reputation an user gets when he first signs in."
+msgstr ""
+
+#: forum/settings/repgain.py:12
+msgid "Maximum reputation a user can gain in one day for being upvoted."
+msgstr ""
+
+#: forum/settings/repgain.py:15
+msgid "Rep gain by upvoted"
+msgstr ""
+
+#: forum/settings/repgain.py:16
+msgid "Reputation a user gains for having one of his posts up voted."
+msgstr ""
+
+#: forum/settings/repgain.py:19
+msgid "Rep lost bu upvote canceled"
+msgstr ""
+
+#: forum/settings/repgain.py:20
+msgid ""
+"Reputation a user loses for having one of the upvotes on his posts canceled."
+msgstr ""
+
+#: forum/settings/repgain.py:23
+msgid "Rep lost by downvoted"
+msgstr ""
+
+#: forum/settings/repgain.py:24
+msgid "Reputation a user loses for having one of his posts down voted."
+msgstr ""
+
+#: forum/settings/repgain.py:27
+msgid "Rep lost by downvoting"
+msgstr ""
+
+#: forum/settings/repgain.py:28
+msgid "Reputation a user loses for down voting a post."
+msgstr ""
+
+#: forum/settings/repgain.py:31
+msgid "Rep gain by downvote canceled"
+msgstr ""
+
+#: forum/settings/repgain.py:32
+msgid ""
+"Reputation a user gains for having one of the downvotes on his posts "
+"canceled."
+msgstr ""
+
+#: forum/settings/repgain.py:35
+msgid "Rep gain by canceling downvote"
+msgstr ""
+
+#: forum/settings/repgain.py:36
+msgid "Reputation a user gains for canceling a downvote."
+msgstr ""
+
+#: forum/settings/repgain.py:39
+msgid "Rep gain by accepted answer"
+msgstr ""
+
+#: forum/settings/repgain.py:40
+msgid "Reputation a user gains for having one of his answers accepted."
+msgstr ""
+
+#: forum/settings/repgain.py:43
+msgid "Rep lost by accepted canceled"
+msgstr ""
+
+#: forum/settings/repgain.py:44
+msgid ""
+"Reputation a user loses for having one of his accepted answers canceled."
+msgstr ""
+
+#: forum/settings/repgain.py:47
+msgid "Rep gain by accepting answer"
+msgstr ""
+
+#: forum/settings/repgain.py:48
+msgid ""
+"Reputation a user gains for accepting an answer to one of his questions."
+msgstr ""
+
+#: forum/settings/repgain.py:51
+msgid "Rep lost by canceling accepted"
+msgstr ""
+
+#: forum/settings/repgain.py:52
+msgid "Reputation a user loses by canceling an accepted answer."
+msgstr ""
+
+#: forum/settings/repgain.py:55
+msgid "Rep lost by post flagged"
+msgstr ""
+
+#: forum/settings/repgain.py:56
+msgid "Reputation a user loses by having one of his posts flagged."
+msgstr ""
+
+#: forum/settings/repgain.py:59
+msgid "Rep lost by post flagged and hidden"
+msgstr ""
+
+#: forum/settings/repgain.py:60
+msgid ""
+"Reputation a user loses by having the last revision of one of his posts "
+"flagged the enough number of times to hide the post."
+msgstr ""
+
+#: forum/settings/repgain.py:63
+msgid "Rep lost by post flagged and deleted"
+msgstr ""
+
+#: forum/settings/repgain.py:64
+msgid ""
+"Reputation a user loses by having the last revision of one of his posts "
+"flagged the enough number of times to delete the post."
+msgstr ""
+
+#: forum/settings/upload.py:5
+msgid "File upload settings"
+msgstr ""
+
+#: forum/settings/upload.py:5
+msgid "File uploads related settings."
+msgstr ""
+
+#: forum/settings/upload.py:8
+msgid "Uploaded files folder"
+msgstr ""
+
+#: forum/settings/upload.py:9
+msgid ""
+"The filesystem path where uploaded files will be stored. Please note that "
+"this folder must exist."
+msgstr ""
+
+#: forum/settings/upload.py:12
+msgid "Uploaded files alias"
+msgstr ""
+
+#: forum/settings/upload.py:13
+msgid ""
+"The url alias for uploaded files. Notice that if you change this setting, "
+"you'll need to restart your site."
+msgstr ""
+
+#: forum/settings/upload.py:16
+msgid "Max file size"
+msgstr ""
+
+#: forum/settings/upload.py:17
+msgid "The maximum allowed file size for uploads in mb."
+msgstr ""
+
+#: forum/settings/voting.py:4
+msgid "Voting rules"
+msgstr ""
+
+#: forum/settings/voting.py:4
+msgid "Configure the voting rules on your site."
+msgstr ""
+
+#: forum/settings/voting.py:7
+msgid "Maximum votes per day"
+msgstr ""
+
+#: forum/settings/voting.py:8
+msgid "The maximum number of votes an user can cast per day."
+msgstr ""
+
+#: forum/settings/voting.py:11
+msgid "Start warning about votes left"
+msgstr ""
+
+#: forum/settings/voting.py:12
+msgid "From how many votes left should an user start to be warned about it."
+msgstr ""
+
+#: forum/settings/voting.py:15
+msgid "Maximum flags per day"
+msgstr ""
+
+#: forum/settings/voting.py:16
+msgid "The maximum number of times an can flag a post per day."
+msgstr ""
+
+#: forum/settings/voting.py:19
+msgid "Flag count to hide post"
+msgstr ""
+
+#: forum/settings/voting.py:20
+msgid ""
+"How many times a post needs to be flagged to be hidden from the main page."
+msgstr ""
+
+#: forum/settings/voting.py:23
+msgid "Flag count to delete post"
+msgstr ""
+
+#: forum/settings/voting.py:24
+msgid "How many times a post needs to be flagged to be deleted."
+msgstr ""
+
+#: forum/settings/voting.py:27
+msgid "Days to cancel a vote"
+msgstr ""
+
+#: forum/settings/voting.py:28
+msgid "How many days an user can cancel a vote after he originaly casted it."
+msgstr ""
+
+#: forum/skins/default/templates/404.html:24
+msgid "Sorry, could not find the page you requested."
+msgstr ""
+
+#: forum/skins/default/templates/404.html:26
+msgid "This might have happened for the following reasons:"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:28
+msgid "this question or answer has been deleted;"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:29
+msgid "url has error - please check it;"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:30
+msgid ""
+"the page you tried to visit is protected or you don't have sufficient "
+"points, see"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:31
+msgid "if you believe this error 404 should not have occured, please"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:32
+msgid "report this problem"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:41
+#: forum/skins/default/templates/500.html:27
+msgid "back to previous page"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:42
+msgid "see all questions"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:43
+msgid "see all tags"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:22
+msgid "sorry, system error"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:24
+msgid "system error log is recorded, error will be fixed as soon as possible"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:25
+msgid "please report the error to the site administrators if you wish"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:28
+msgid "see latest questions"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:29
+msgid "see tags"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:12
+#: forum/skins/default/templates/book.html:105
+#: forum/skins/default/templates/question_summary_list_roll.html:14
+#: forum/skins/default/templates/question_list/item.html:10
+#: forum/views/commands.py:82
+msgid "votes"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:14
+msgid "this answer has been accepted to be correct"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:16
+#: forum/skins/default/templates/question_summary_list_roll.html:13
+#: forum/skins/default/templates/question_list/item.html:14
+msgid "answers"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:20
+#: forum/skins/default/templates/book.html:115
+#: forum/skins/default/templates/question_summary_list_roll.html:15
+#: forum/skins/default/templates/question_list/item.html:18
+msgid "views"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:34
+#: forum/skins/default/templates/question.html:234
+#: forum/skins/default/templates/question_summary_list_roll.html:52
+#: forum/skins/default/templates/tags.html:49
+#: forum/skins/default/templates/question_list/item.html:29
+msgid "see questions tagged"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:34
+#: forum/skins/default/templates/book.html:125
+#: forum/skins/default/templates/question.html:234
+#: forum/skins/default/templates/question_summary_list_roll.html:52
+#: forum/skins/default/templates/tags.html:49
+#: forum/skins/default/templates/question_list/item.html:29
+msgid "using tags"
+msgstr ""
+
+#: forum/skins/default/templates/about.html:5
+#: forum/skins/default/templates/about.html:9
+msgid "About"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:4
+msgid "Account functions"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:29
+#: forum/skins/default/templates/auth/auth_settings.html:31
+msgid "Change password"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:30
+msgid "Give your  account a new password."
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:32
+msgid "Change email "
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:33
+msgid "Add or update the email address associated with your account."
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:35
+msgid "Change OpenID"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:36
+msgid "Change openid associated to your account"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:39
+msgid "Delete account"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:40
+msgid "Erase your username and all your data from website"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:5
+#: forum/skins/default/templates/answer_edit.html:39
+msgid "Edit answer"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:18
+#: forum/skins/default/templates/answer_edit.html:21
+#: forum/skins/default/templates/ask.html:19
+#: forum/skins/default/templates/ask.html:22
+#: forum/skins/default/templates/question_edit.html:19
+#: forum/skins/default/templates/question_edit.html:22
+msgid "hide preview"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:21
+#: forum/skins/default/templates/ask.html:22
+#: forum/skins/default/templates/question_edit.html:22
+msgid "show preview"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:39
+#: forum/skins/default/templates/question_edit.html:63
+#: forum/skins/default/templates/question_retag.html:56
+#: forum/skins/default/templates/revisions_answer.html:36
+#: forum/skins/default/templates/revisions_question.html:35
+msgid "back"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:44
+#: forum/skins/default/templates/question_edit.html:68
+#: forum/skins/default/templates/revisions_answer.html:50
+#: forum/skins/default/templates/revisions_question.html:49
+msgid "revision"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:47
+#: forum/skins/default/templates/question_edit.html:72
+msgid "select revision"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:54
+#: forum/skins/default/templates/ask.html:93
+#: forum/skins/default/templates/question.html:184
+#: forum/skins/default/templates/question_edit.html:89
+msgid "Toggle the real time Markdown editor preview"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:54
+#: forum/skins/default/templates/ask.html:93
+#: forum/skins/default/templates/question.html:185
+#: forum/skins/default/templates/question_edit.html:89
+msgid "toggle preview"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:63
+#: forum/skins/default/templates/question_edit.html:115
+#: forum/skins/default/templates/question_retag.html:77
+msgid "Save edit"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:64
+#: forum/skins/default/templates/close.html:29
+#: forum/skins/default/templates/feedback.html:50
+#: forum/skins/default/templates/question_edit.html:116
+#: forum/skins/default/templates/question_retag.html:78
+#: forum/skins/default/templates/reopen.html:30
+#: forum/skins/default/templates/users/edit.html:87
+msgid "Cancel"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:4
+msgid "answer tips"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:7
+msgid "please make your answer relevant to this community"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:10
+msgid "try to give an answer, rather than engage into a discussion"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:13
+msgid "please try to provide details"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:16
+#: forum/skins/default/templates/question_edit_tips.html:18
+msgid "be clear and concise"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:20
+#: forum/skins/default/templates/question_edit_tips.html:22
+msgid "see frequently asked questions"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:26
+#: forum/skins/default/templates/question_edit_tips.html:28
+msgid "Markdown tips"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:29
+#: forum/skins/default/templates/question_edit_tips.html:31
+msgid "*italic* or __italic__"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:32
+#: forum/skins/default/templates/question_edit_tips.html:34
+msgid "**bold** or __bold__"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:35
+#: forum/skins/default/templates/question_edit_tips.html:37
+msgid "link"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:35
+#: forum/skins/default/templates/answer_edit_tips.html:39
+#: forum/skins/default/templates/question_edit_tips.html:37
+#: forum/skins/default/templates/question_edit_tips.html:42
+msgid "text"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:39
+#: forum/skins/default/templates/question_edit_tips.html:42
+msgid "image"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:43
+#: forum/skins/default/templates/question_edit_tips.html:46
+msgid "numbered list:"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:48
+#: forum/skins/default/templates/question_edit_tips.html:51
+msgid "basic HTML tags are also supported"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:52
+#: forum/skins/default/templates/question_edit_tips.html:55
+msgid "learn more about Markdown"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:5
+#: forum/skins/default/templates/ask.html:57
+msgid "Ask a question"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:64
+msgid "login to post question info"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:70
+#, python-format
+msgid ""
+"must have valid %(email)s to post, \n"
+"                            see %(email_validation_faq_url)s\n"
+"                            "
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:108
+msgid "(required)"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:115
+msgid "Login/signup to post your question"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:117
+msgid "Ask your question"
+msgstr ""
+
+#: forum/skins/default/templates/badge.html:6
+#: forum/skins/default/templates/badge.html:17
+msgid "Badge"
+msgstr ""
+
+#: forum/skins/default/templates/badge.html:26
+msgid "The users have been awarded with badges:"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:6
+msgid "Badges summary"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:17
+msgid "Badges"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:21
+msgid "Community gives you awards for your questions, answers and votes."
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:22
+#, python-format
+msgid ""
+"Below is the list of available badges and number \n"
+"    of times each type of badge has been awarded. Give us feedback at %"
+"(feedback_faq_url)s.\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:50
+msgid "Community badges"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:56
+msgid "gold badge description"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:64
+msgid "silver badge description"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:67
+msgid "bronze badge: often given as a special honor"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:71
+msgid "bronze badge description"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:7
+msgid "reading channel"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:26
+msgid "[author]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:30
+msgid "[publisher]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:34
+msgid "[publication date]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:38
+msgid "[price]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:39
+msgid "currency unit"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:42
+msgid "[pages]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:43
+msgid "pages abbreviation"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:46
+msgid "[tags]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:56
+msgid "author blog"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:62
+msgid "book directory"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:66
+msgid "buy online"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:79
+msgid "reader questions"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:82
+msgid "ask the author"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:88
+#: forum/skins/default/templates/book.html:93
+msgid "this question was selected as favorite"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:88
+#: forum/skins/default/templates/book.html:93
+msgid "number of times"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:108
+msgid "the answer has been accepted to be correct"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:147
+msgid "subscribe to book RSS feed"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:147
+msgid "subscribe to the questions feed"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:6
+#: forum/skins/default/templates/close.html:16
+msgid "Close question"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:19
+msgid "Close the question"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:25
+msgid "Reasons"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:28
+msgid "OK to close"
+msgstr ""
+
+#: forum/skins/default/templates/email_base.html:31
+msgid "home"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:11
+msgid "Frequently Asked Questions "
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:16
+msgid "What kinds of questions can I ask here?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:17
+msgid ""
+"Most importantly - questions should be <strong>relevant</strong> to this "
+"community."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:18
+msgid ""
+"Before asking the question - please make sure to use search to see whether "
+"your question has alredy been answered."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:21
+msgid "What questions should I avoid asking?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:22
+msgid ""
+"Please avoid asking questions that are not relevant to this community, too "
+"subjective and argumentative."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:27
+msgid "What should I avoid in my answers?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:28
+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 ""
+
+#: forum/skins/default/templates/faq.html:32
+msgid "Who moderates this community?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:33
+msgid "The short answer is: <strong>you</strong>."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:34
+msgid "This website is moderated by the users."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:35
+msgid ""
+"The reputation system allows users earn the authorization to perform a "
+"variety of moderation tasks."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:40
+msgid "How does reputation system work?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:41
+msgid "Rep system summary"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:42
+msgid ""
+"For example, if you ask an interesting question or give a helpful answer, "
+"your input will be upvoted. On the other hand if the answer is misleading - "
+"it will be downvoted. Each vote in favor will generate <strong>10</strong> "
+"points, each vote against will subtract <strong>2</strong> points. There is "
+"a limit of <strong>200</strong> points that can be accumulated per question "
+"or answer. The table below explains reputation point requirements for each "
+"type of moderation task."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:53
+#: forum/skins/default/templates/users/votes.html:15
+#: forum/views/commands.py:77
+msgid "upvote"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:57
+msgid "use tags"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:62
+msgid "add comments"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:66
+#: forum/skins/default/templates/users/votes.html:17
+#: forum/views/commands.py:77
+msgid "downvote"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:69
+msgid "open and close own questions"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:73
+msgid "retag questions"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:78
+msgid "edit community wiki questions"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:83
+msgid "edit any answer"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:87
+msgid "open any closed question"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:91
+msgid "delete any comment"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:95
+msgid "delete any questions and answers and perform other moderation tasks"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:103
+msgid "how to validate email title"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:105
+#, python-format
+msgid ""
+"how to validate email info with %(send_email_key_url)s %(gravatar_faq_url)s"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:110
+msgid "what is gravatar"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:111
+msgid "gravatar faq info"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:114
+msgid "To register, do I need to create new password?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:115
+msgid ""
+"No, you don't have to. You can login through any service that supports "
+"OpenID, e.g. Google, Yahoo, AOL, etc."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:116
+msgid "Login now!"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:121
+msgid "Why other people can edit my questions/answers?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:122
+msgid "Goal of this site is..."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:122
+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 ""
+
+#: forum/skins/default/templates/faq.html:123
+msgid "If this approach is not for you, we respect your choice."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:127
+msgid "Still have questions?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:128
+#, python-format
+msgid ""
+"Please ask your question at %(ask_question_url)s, help make our community "
+"better!"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:130
+#: forum/skins/default/templates/header.html:30
+#: forum/skins/default/templates/header.html:55 forum/views/readers.py:76
+msgid "questions"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:130
+msgid "."
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:6
+msgid "Feedback"
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:11
+msgid "Give us your feedback!"
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:17
+#, python-format
+msgid ""
+"\n"
+"            <span class='big strong'>Dear %(user_name)s</span>, we look "
+"forward to hearing your feedback. \n"
+"            Please type and send us your message below.\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:24
+msgid ""
+"\n"
+"            <span class='big strong'>Dear visitor</span>, we look forward to "
+"hearing your feedback.\n"
+"            Please type and send us your message below.\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:41
+msgid "(this field is required)"
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:49
+msgid "Send Feedback"
+msgstr ""
+
+#: forum/skins/default/templates/footer.html:7
+#: forum/skins/default/templates/header.html:16
+#: forum/skins/default/templates/index.html:12
+msgid "about"
+msgstr ""
+
+#: forum/skins/default/templates/footer.html:8
+#: forum/skins/default/templates/header.html:17
+#: forum/skins/default/templates/index.html:13
+#: forum/skins/default/templates/question_edit_tips.html:22
+msgid "faq"
+msgstr ""
+
+#: forum/skins/default/templates/footer.html:9
+msgid "privacy policy"
+msgstr ""
+
+#: forum/skins/default/templates/footer.html:18
+msgid "give feedback"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:9
+msgid "administration"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:12
+msgid "logout"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:14
+msgid "login"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:24
+msgid "back to home page"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:32
+#: forum/skins/default/templates/header.html:57
+msgid "users"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:33
+#: forum/skins/default/templates/users/signature.html:9
+#: forum/skins/default/templates/users/signature.html:15
+#: forum/skins/default/templates/users/signature.html:21
+#: forum/templatetags/extra_tags.py:167 forum/templatetags/extra_tags.py:196
+msgid "badges"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:34
+msgid "unanswered questions"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:36
+msgid "ask a question"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:51
+msgid "search"
+msgstr ""
+
+#: forum/skins/default/templates/index.html:9
+msgid "welcome to "
+msgstr ""
+
+#: forum/skins/default/templates/logout.html:6
+#: forum/skins/default/templates/logout.html:16
+msgid "Logout"
+msgstr ""
+
+#: forum/skins/default/templates/logout.html:19
+msgid ""
+"As a registered user you can login with your OpenID, log out of the site or "
+"permanently remove your account."
+msgstr ""
+
+#: forum/skins/default/templates/logout.html:20
+msgid "Logout now"
+msgstr ""
+
+#: forum/skins/default/templates/notarobot.html:3
+msgid "Please prove that you are a Human Being"
+msgstr ""
+
+#: forum/skins/default/templates/notarobot.html:10
+msgid "I am a Human Being"
+msgstr ""
+
+#: forum/skins/default/templates/pagesize.html:6
+msgid "posts per page"
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:6
+#: forum/skins/default/templates/paginator.html:7
+msgid "previous"
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:19
+msgid "current page"
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:22
+#: forum/skins/default/templates/paginator.html:29
+msgid "page number "
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:22
+#: forum/skins/default/templates/paginator.html:29
+msgid "number - make blank in english"
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:33
+msgid "next page"
+msgstr ""
+
+#: forum/skins/default/templates/post_contributor_info.html:9
+#, python-format
+msgid ""
+"\n"
+"                one revision\n"
+"            "
+msgid_plural ""
+"\n"
+"                %(rev_count)s revisions\n"
+"            "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/post_contributor_info.html:24
+msgid "posted"
+msgstr ""
+
+#: forum/skins/default/templates/post_contributor_info.html:45
+msgid "updated"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:6
+#: forum/skins/default/templates/privacy.html:11
+msgid "Privacy policy"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:15
+msgid "general message about privacy"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:18
+msgid "Site Visitors"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:20
+msgid "what technical information is collected about visitors"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:23
+msgid "Personal Information"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:25
+msgid "details on personal information policies"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:28
+msgid "Other Services"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:30
+msgid "details on sharing data with third parties"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:35
+msgid "cookie policy details"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:37
+msgid "Policy Changes"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:38
+msgid "how privacy policies can be changed"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:70
+#: forum/skins/default/templates/sidebar/recent_tags.html:9
+#, python-format
+msgid "see questions tagged '%(tagname)s'"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:87
+#, python-format
+msgid ""
+"The question has been closed for the following reason \"%(close_reason)s\" by"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:89
+#, python-format
+msgid "close date %(closed_at)s"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:97
+#, python-format
+msgid ""
+"\n"
+"                    One Answer:\n"
+"                    "
+msgid_plural ""
+"\n"
+"                    %(counter)s Answers:\n"
+"                    "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/question.html:105
+msgid "oldest answers will be shown first"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:105
+msgid "oldest answers"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:107
+msgid "newest answers will be shown first"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:107
+msgid "newest answers"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:109
+msgid "most voted answers will be shown first"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:109
+msgid "popular answers"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:157
+msgid "Your answer"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:159
+msgid "Be the first one to answer this question!"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:165
+msgid "you can answer anonymously and then login"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:169
+msgid "answer your own question only to give an answer"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:171
+msgid "please only give an answer, no discussions"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:207
+msgid "Login/Signup to Post Your Answer"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:210
+msgid "Answer Your Own Question"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:212
+msgid "Answer the question"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:229
+msgid "Question tags"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:239
+msgid "question asked"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:242
+msgid "question was seen"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:242
+msgid "times"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:245
+msgid "last updated"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:250
+msgid "Related questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_edit.html:5
+#: forum/skins/default/templates/question_edit.html:63
+msgid "Edit question"
+msgstr ""
+
+#: forum/skins/default/templates/question_edit_tips.html:4
+msgid "question tips"
+msgstr ""
+
+#: forum/skins/default/templates/question_edit_tips.html:9
+#, python-format
+msgid ""
+"\n"
+"                ask a question relevant to the %(app_title)s community \n"
+"                "
+msgstr ""
+
+#: forum/skins/default/templates/question_edit_tips.html:15
+msgid "please try provide enough details"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:5
+#: forum/skins/default/templates/question_retag.html:56
+msgid "Change tags"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:44
+msgid "up to 5 tags, less than 20 characters each"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:86
+msgid "Why use and modify tags?"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:89
+msgid "tags help us keep Questions organized"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:97
+msgid "tag editors receive special awards from the community"
+msgstr ""
+
+#: forum/skins/default/templates/questions.html:7
+msgid "Questions"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:6
+#: forum/skins/default/templates/reopen.html:16
+msgid "Reopen question"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:19
+msgid "Open the previously closed question"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:22
+msgid "The question was closed for the following reason "
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:22
+msgid "reason - leave blank in english"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:22
+msgid "on "
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:22
+msgid "date closed"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:29
+msgid "Reopen this question"
+msgstr ""
+
+#: forum/skins/default/templates/revisions_answer.html:7
+#: forum/skins/default/templates/revisions_answer.html:36
+#: forum/skins/default/templates/revisions_question.html:7
+#: forum/skins/default/templates/revisions_question.html:35
+msgid "Revision history"
+msgstr ""
+
+#: forum/skins/default/templates/revisions_answer.html:48
+#: forum/skins/default/templates/revisions_question.html:47
+msgid "click to hide/show revision"
+msgstr ""
+
+#: forum/skins/default/templates/revisions_answer.html:56
+#: forum/templatetags/node_tags.py:62
+msgid "edit"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:3
+msgid "Subscription"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:8
+msgid "You were automatically subscribed to this question."
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:10
+msgid "You are subscribed to this question."
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:13
+msgid "You are not subscribed to this question."
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:18
+#: forum/views/commands.py:323
+msgid "unsubscribe me"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:20
+#: forum/views/commands.py:323
+msgid "subscribe me"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:24
+#, python-format
+msgid ""
+"\n"
+"            (you can adjust your notification settings on your <a href=\"%"
+"(profile_url)s?sort=email_subscriptions\">profile</a>)\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:29
+msgid "Once you sign in you will be able to subscribe for any updates here"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:4
+#: forum/skins/default/templates/question_list/tag_selector.html:6
+msgid "Interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:10
+#: forum/skins/default/templates/tag_selector.html:27
+#: forum/skins/default/templates/question_list/related_tags.html:9
+#: forum/skins/default/templates/question_list/tag_selector.html:12
+#: forum/skins/default/templates/question_list/tag_selector.html:29
+#, python-format
+msgid "see questions tagged '%(tag_name)s'"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:14
+#: forum/skins/default/templates/question_list/tag_selector.html:16
+#, python-format
+msgid "remove '%(tag_name)s' from the list of interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:20
+#: forum/skins/default/templates/tag_selector.html:37
+#: forum/skins/default/templates/question_list/tag_selector.html:22
+#: forum/skins/default/templates/question_list/tag_selector.html:39
+msgid "Add"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:21
+#: forum/skins/default/templates/question_list/tag_selector.html:23
+msgid "Ignored tags"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:31
+#: forum/skins/default/templates/question_list/tag_selector.html:33
+#, python-format
+msgid "remove '%(tag_name)s' from the list of ignored tags"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:40
+#: forum/skins/default/templates/question_list/tag_selector.html:42
+msgid "keep ignored questions hidden"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:6
+#: forum/skins/default/templates/tags.html:30
+msgid "Tag list"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:32
+msgid "sorted alphabetically"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:32
+msgid "by name"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:33
+msgid "sorted by frequency of tag use"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:33
+msgid "by popularity"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:39
+msgid "All tags matching query"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:39
+msgid "all tags - make this empty in english"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:42
+msgid "Nothing found"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:5
+#: forum/skins/default/templates/auth/auth_settings.html:7
+msgid "Authentication settings"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:9
+msgid ""
+"These are the external authentication providers currently associated with "
+"your account."
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:12
+msgid "remove"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:17
+msgid ""
+"You currently have no external authentication provider associated with your "
+"account."
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:19
+msgid "Add new provider"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:21
+msgid "This is where you can change your password. Make sure you remember it!"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:24
+msgid ""
+"You can set up a password for your account, so you can login using standard "
+"username and password!"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:31
+msgid "Create password"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:5
+msgid "Connect your OpenID with this site"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:8
+msgid "Connect your OpenID with your account on this site"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:12
+msgid "You are here for the first time with "
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:13
+msgid ""
+"Please create your screen name and save your email address. Saved email "
+"address will let you subscribe for the updates on the most interesting "
+"questions and will be used to create and retrieve your unique avatar image. "
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:15
+msgid "This account already exists, please use another."
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:30
+msgid "Sorry, looks like we have some errors:"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:47
+msgid "Screen name label"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:54
+msgid "Email address label"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:60
+#: forum/skins/default/templates/auth/signup.html:18
+msgid "receive updates motivational blurb"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:64
+#: forum/skins/default/templates/auth/signup.html:22
+msgid "please select one of the options above"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:67
+msgid "Tag filter tool will be your right panel, once you log in."
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:68
+msgid "create account"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:77
+msgid "Existing account"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:78
+msgid "user name"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:79
+msgid "password"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:86
+msgid "Register"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:87
+msgid "Forgot your password?"
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:6
+#: forum/skins/default/templates/auth/temp_login_email.html:6
+msgid "Greetings from the Q&A forum"
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:8
+msgid "To make use of the Forum, please follow the link below:"
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:12
+msgid "Following the link above will help us verify your email address."
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:14
+#: forum/skins/default/templates/auth/temp_login_email.html:14
+msgid ""
+"If you beleive that this message was sent in mistake -\n"
+"    no further action is needed. Just ingore this email, we apologize\n"
+"    for any inconvenience"
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:18
+#: forum/skins/default/templates/auth/temp_login_email.html:18
+#: forum/skins/default/templates/notifications/answeraccepted.html:15
+#: forum/skins/default/templates/notifications/newanswer.html:25
+#: forum/skins/default/templates/notifications/newcomment.html:32
+#: forum/skins/default/templates/notifications/newmember.html:15
+#: forum/skins/default/templates/notifications/newquestion.html:25
+msgid ""
+"Sincerely,<br />\n"
+"    Forum Administrator"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:6
+msgid "Login"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:24
+msgid "User login"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:36
+#: forum/skins/default/templates/auth/signin.html:86
+#: forum/skins/default/templates/auth/signin.html:92
+msgid "Or..."
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:39
+msgid "Click to sign in through any of these services."
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:44
+msgid "Validate my email after I login."
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:94
+msgid "Click"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:94
+msgid "if you're having troubles signing in."
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:98
+msgid "Enter your "
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:154
+msgid "Why use OpenID?"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:157
+msgid "with openid it is easier"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:160
+msgid "reuse openid"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:163
+msgid "openid is widely adopted"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:166
+msgid "openid is supported open standard"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:171
+msgid "Find out more"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:172
+msgid "Get OpenID"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:4
+msgid "Signup"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:8
+msgid "Create login name and password"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:10
+msgid "Traditional signup info"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:31
+msgid "Create Account"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:32
+msgid "or"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:33
+msgid "return to login page"
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_email.html:8
+msgid "You're seeing this because someone requested a temporary login link"
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_email.html:12
+msgid "Following the link above will give you access to your account."
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:5
+msgid "Request temporary login key"
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:7
+msgid "Account: request temporary login key"
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:8
+msgid ""
+"\n"
+"    If you're experiencing problems accessing your account, or if you forgot "
+"your password,\n"
+"    here you can request a temporary login key. Fill out your account email "
+"and we'll send you a temporary access link that\n"
+"    will enable you to access your account. This token is valid only once "
+"and for a limited period of time.\n"
+" "
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:25
+msgid "Send link"
+msgstr ""
+
+#: forum/skins/default/templates/node/accept_button.html:5
+#, python-format
+msgid "%(who)s has selected this answer as the correct answer"
+msgstr ""
+
+#: forum/skins/default/templates/node/accept_button.html:5
+msgid "mark this answer as the accepted answer"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:22
+msgid "I like this comment (click again to cancel)"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:26
+msgid "Edit comment"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:30
+msgid "Delete comment"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:42
+#, python-format
+msgid "showing %(showing)s of %(total)s"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:44
+msgid "show all"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:47
+msgid "add new comment"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:55
+msgid " add comment"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:58
+#, python-format
+msgid ""
+"\n"
+"                have <span class=\"comments-char-left-count\">%(max_length)"
+"s</span> characters left\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:71
+msgid "just now"
+msgstr ""
+
+#: forum/skins/default/templates/node/favorite_mark.html:3
+msgid "mark/unmark this question as favorite (click again to cancel)"
+msgstr ""
+
+#: forum/skins/default/templates/node/vote_buttons.html:3
+msgid "I like this post (click again to cancel)"
+msgstr ""
+
+#: forum/skins/default/templates/node/vote_buttons.html:7
+msgid "current number of votes"
+msgstr ""
+
+#: forum/skins/default/templates/node/vote_buttons.html:10
+msgid "I dont like this post (click again to cancel)"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/answeraccepted.html:6
+#: forum/skins/default/templates/notifications/digest.html:7
+#: forum/skins/default/templates/notifications/newanswer.html:6
+#: forum/skins/default/templates/notifications/newcomment.html:6
+#: forum/skins/default/templates/notifications/newmember.html:6
+#: forum/skins/default/templates/notifications/newquestion.html:6
+msgid "Hello"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/answeraccepted.html:9
+#, python-format
+msgid ""
+"\n"
+"        Just to let you know that %(accepter)s has just accepted %"
+"(answer_author)s's answer on his question\n"
+"        <a href=\"%(app_url)s%(question_url)s\">%(question_title)s</a>:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:9
+#, python-format
+msgid ""
+"\n"
+"    This is the %(digest_type)s activity digest for %(app_title)s\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:15
+#, python-format
+msgid ""
+"\n"
+"            %(nusers_count)s new user%(nusers_count_pluralize)s joined the %"
+"(app_title)s community:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:28
+#, python-format
+msgid ""
+"\n"
+"            %(question_count)s of your subscriptions have updates:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:35
+msgid "On question "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:37
+#, python-format
+msgid ""
+"\n"
+"                    %(answer_count)s new answer%(answer_count_pluralize)s\n"
+"                "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:42
+#, python-format
+msgid ""
+"\n"
+"                    %(comment_count)s new comment%(comment_count_pluralize)"
+"s\n"
+"                "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:46
+msgid "on your own post(s)"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:50
+msgid "an answer was accepted"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:59
+#, python-format
+msgid ""
+"\n"
+"            %(question_count)s new question%(question_count_pluralize)s\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:63
+msgid "matching your interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:65
+msgid "posted :"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:71
+#, python-format
+msgid ""
+"\n"
+"                    Posted by %(author_name)s in %(question_time)s\n"
+"                "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:7
+#, python-format
+msgid ""
+"\n"
+"    Hello, this is a %(site_title)s forum feedback message\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:13
+msgid "Sender"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:15
+#: forum/skins/default/templates/notifications/feedback.html:18
+#: forum/skins/default/templates/users/info.html:93
+msgid "email"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:17
+msgid "anonymous"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:25
+msgid "Message body:"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newanswer.html:9
+#, python-format
+msgid ""
+"\n"
+"        %(author_name)s has just posted a new answer on %(app_title)s to the "
+"question\n"
+"        <a href=\"%(app_url)s%(question_url)s\">%(question_title)s\"</a>:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newanswer.html:20
+#: forum/skins/default/templates/notifications/newcomment.html:28
+#: forum/skins/default/templates/notifications/newquestion.html:20
+msgid ""
+"\n"
+"        Don't forget to come over and cast your vote.\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newcomment.html:9
+#, python-format
+msgid ""
+"\n"
+"            %(author_name)s has just posted a comment on\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newcomment.html:14
+#, python-format
+msgid ""
+"\n"
+"                the answer posted by <a href=\"%(app_url)s%(poster_url)s\">%"
+"(poster_name)s</a> to\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newcomment.html:19
+#, python-format
+msgid ""
+"\n"
+"             the question  <a href=\"%(app_url)s%(question_url)s\">%"
+"(question_title)s</a>\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newmember.html:9
+#, python-format
+msgid ""
+"\n"
+"        %(newmember_name)s has just joined %(app_title)s. You can visit %"
+"(newmember_name)s's profile using the following link: <br />\n"
+"        <a href=\"%(app_url)s%(newmember_url)s\">%(newmember_name)s profile</"
+"a>\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newquestion.html:9
+#, python-format
+msgid ""
+"\n"
+"        %(author_name)s has just posted a new question on %(app_title)s, "
+"with title\n"
+"        <a href=\"%(app_url)s%(question_url)s\">%(question_title)s</a> and "
+"tagged <em>%(question_tags)s</em>:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/base.html:13
+msgid "OSQA administration area"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/base.html:26
+msgid "Administration menu"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:7
+msgid "Dashboard"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:10
+msgid "Welcome to the OSQA administration area."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:17
+msgid "Site statistics"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:21
+#: forum/skins/default/templates/osqaadmin/index.html:26
+msgid "in the last 24 hours"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:31
+msgid "user"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:31
+msgid "joined in the last 24 hours"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:37
+msgid "Site status"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:42
+msgid ""
+"Your site is running in bootstrap mode, click the button bellow to revert to "
+"defaults."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:45
+msgid ""
+"Your site is running in standard mode, click the button bellow to run in "
+"bootstrap mode."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:47
+msgid ""
+"Your site is running with some customized settings, click the buttons bellow "
+"to run with defaults or in bootstrap mode"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:51
+msgid "Are you sure you want to revert to the defaults?"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:51
+msgid "revert to defaults"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:54
+msgid "Are you sure you want to run bootstrap mode?"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:54
+msgid "go bootstrap"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:59
+msgid "Recalculate scores and reputation"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:60
+msgid "This is a heavy operation, are you sure?"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:60
+msgid "Recalculate"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:65
+msgid "Recent activity"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/item.html:12
+msgid "this question has an accepted answer"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/related_tags.html:6
+msgid "Related tags"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:4
+msgid "most recently updated questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:4
+msgid "active"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:5
+msgid "most recently asked questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:5
+msgid "newest"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:6
+msgid "hottest questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:6
+msgid "hottest"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:7
+msgid "most voted questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:7
+msgid "most voted"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:5
+msgid "Found by tags"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:9
+msgid "Search results"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:11
+msgid "Found by title"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:15
+msgid "Unanswered questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:17
+#: forum/skins/default/templates/users/subscriptions.html:74
+msgid "All questions"
+msgstr ""
+
+#: forum/skins/default/templates/sidebar/recent_awards.html:4
+msgid "Recent awards"
+msgstr ""
+
+#: forum/skins/default/templates/sidebar/recent_awards.html:15
+msgid "all awards"
+msgstr ""
+
+#: forum/skins/default/templates/sidebar/recent_tags.html:4
+msgid "Recent tags"
+msgstr ""
+
+#: forum/skins/default/templates/sidebar/recent_tags.html:12
+msgid "popular tags"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:6
+msgid "Edit user profile"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:19
+msgid "edit profile"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:31
+msgid "image associated with your email address"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:31
+#, python-format
+msgid "avatar, see %(gravatar_faq_url)s"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:36
+#: forum/skins/default/templates/users/info.html:52
+msgid "Registered user"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:43
+msgid "Screen Name"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:86
+#: forum/skins/default/templates/users/subscriptions.html:116
+msgid "Update"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:22
+#: forum/skins/default/templates/users/signature.html:6
+#: forum/skins/default/templates/users/users.html:26
+msgid "reputation"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:32
+msgid "Moderate this user"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:44
+msgid "update profile"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:56
+msgid "real name"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:61
+msgid "member for"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:66
+msgid "last seen"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:72
+msgid "user website"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:78
+msgid "location"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:86
+msgid "age"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:87
+msgid "age unit"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:100
+msgid "todays unused votes"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:101
+msgid "votes left"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:13
+#, python-format
+msgid ""
+"\n"
+"                <span class=\"count\">1</span> Question\n"
+"                "
+msgid_plural ""
+"\n"
+"                <span class=\"count\">%(counter)s</span> Questions\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:29
+#, python-format
+msgid ""
+"\n"
+"                <span class=\"count\">1</span> Answer\n"
+"                "
+msgid_plural ""
+"\n"
+"                <span class=\"count\">%(counter)s</span> Answers\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:42
+#, python-format
+msgid "the answer has been voted for %(vote_count)s times"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:42
+msgid "this answer has been selected as correct"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:58
+#, python-format
+msgid ""
+"\n"
+"                    <span class=\"count\">1</span> Vote\n"
+"                "
+msgid_plural ""
+"\n"
+"                    <span class=\"count\">%(cnt)s</span> Votes\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:69
+msgid "thumb up"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:70
+msgid "user has voted up this many times"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:74
+msgid "thumb down"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:75
+msgid "user voted down this many times"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:84
+#, python-format
+msgid ""
+"\n"
+"                    <span class=\"count\">1</span> Tag\n"
+"                "
+msgid_plural ""
+"\n"
+"                    <span class=\"count\">%(counter)s</span> Tags\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:97
+#, python-format
+msgid ""
+"see other questions with %(view_user)s's contributions tagged '%(tag_name)s' "
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:112
+#, python-format
+msgid ""
+"\n"
+"            <span class=\"count\">1</span> Badge\n"
+"            "
+msgid_plural ""
+"\n"
+"            <span class=\"count\">%(counter)s</span> Badges\n"
+"            "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/subscriptions.html:8
+msgid "Notifications and subscription settings"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:10
+msgid ""
+"\n"
+"        Here you can decide which types of notifications you wish to "
+"receive, and it's frequency.<br />\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:14
+msgid ""
+"\n"
+"        Currently you have notifications enabled. You can always stop all "
+"notifications without loosing your settings and restart them afterwards.<br /"
+">\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:18
+msgid ""
+"\n"
+"        Currently you have notifications disabled. You can enable them "
+"clicking on the <strong>Start notifications</strong> button bellow.<br />\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:28
+msgid "Notify me when:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:32
+msgid "A new member joins"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:36
+msgid "A new question is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:40
+msgid "A new question matching my interesting tags is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:44
+msgid "There's an update on one of my subscriptions"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:52
+msgid "Auto subscribe me to:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:57
+msgid "Questions I ask"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:60
+msgid "Questions I answer"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:63
+msgid "Questions I comment"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:68
+msgid "Questions I view"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:71
+msgid "All questions matching my interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:82
+msgid "On my subscriptions, notify me when:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:87
+msgid "An answer is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:90
+msgid "A comment on one of my posts is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:95
+msgid "A comment is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:98
+msgid "An answer is accepted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:106
+msgid "More:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:111
+msgid ""
+"Notify me when someone replys to one of my comments on any post using the "
+"<pre>@username</pre> notation"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:118
+msgid "Stop notifications"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:120
+msgid "Start notifications"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:7
+msgid "User profile"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:7
+msgid "overview"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:9
+msgid "recent activity"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:11
+msgid "graph of user reputation"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:12
+msgid "reputation history"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:15 forum/views/users.py:196
+msgid "user vote record"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:15
+msgid "casted votes"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:18
+msgid "questions that user selected as his/her favorite"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:19
+msgid "favorites"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:22
+msgid "email subscription settings"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:23
+msgid "subscriptions"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:6
+#: forum/skins/default/templates/users/users.html:24
+msgid "Users"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:27
+msgid "recent"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:28
+msgid "oldest"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:29
+msgid "by username"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:35
+#, python-format
+msgid "users matching query %(suser)s:"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:39
+msgid "Nothing found."
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:168 forum/templatetags/extra_tags.py:195
+msgid "reputation points"
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:248
+msgid "2 days ago"
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:250
+msgid "yesterday"
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:252
+#, python-format
+msgid "%(hr)d hour ago"
+msgid_plural "%(hr)d hours ago"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/templatetags/extra_tags.py:254
+#, python-format
+msgid "%(min)d min ago"
+msgid_plural "%(min)d mins ago"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/templatetags/node_tags.py:58
+msgid "permanent link"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:58
+msgid "answer permanent link"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:64
+msgid "retag"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:68
+msgid "reopen"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:70
+msgid "close"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:73 forum/views/commands.py:124
+#: forum/views/commands.py:136
+msgid "flag"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:79
+msgid ""
+"report as offensive (i.e containing spam, advertising, malicious text, etc.)"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:82
+msgid "delete"
+msgstr ""
+
+#: forum/templatetags/question_list_tags.py:57
+msgid "<strong>Newest</strong> questions are shown first. "
+msgstr ""
+
+#: forum/templatetags/question_list_tags.py:58
+msgid "Questions are sorted by the <strong>time of last update</strong>."
+msgstr ""
+
+#: forum/templatetags/question_list_tags.py:59
+msgid "Questions sorted by <strong>number of responses</strong>."
+msgstr ""
+
+#: forum/templatetags/question_list_tags.py:60
+msgid "Questions are sorted by the <strong>number of votes</strong>."
+msgstr ""
+
+#: forum/templatetags/user_tags.py:58 forum/views/readers.py:293
+#, python-format
+msgid "Revision n. %(rev_number)d"
+msgstr ""
+
+#: forum/utils/forms.py:32
+msgid "this field is required"
+msgstr ""
+
+#: forum/utils/forms.py:47
+msgid "choose a username"
+msgstr ""
+
+#: forum/utils/forms.py:52
+msgid "user name is required"
+msgstr ""
+
+#: forum/utils/forms.py:53
+msgid "sorry, this name is taken, please choose another"
+msgstr ""
+
+#: forum/utils/forms.py:54
+msgid "sorry, this name is not allowed, please choose another"
+msgstr ""
+
+#: forum/utils/forms.py:55
+msgid "sorry, there is no user with this name"
+msgstr ""
+
+#: forum/utils/forms.py:56
+msgid "sorry, we have a serious error - user name is taken by several users"
+msgstr ""
+
+#: forum/utils/forms.py:57
+msgid "user name can only consist of letters, empty space and underscore"
+msgstr ""
+
+#: forum/utils/forms.py:105
+msgid "your email address"
+msgstr ""
+
+#: forum/utils/forms.py:106
+msgid "email address is required"
+msgstr ""
+
+#: forum/utils/forms.py:108
+msgid "this email is already used by someone else, please choose another"
+msgstr ""
+
+#: forum/utils/forms.py:133
+msgid "choose password"
+msgstr ""
+
+#: forum/utils/forms.py:134
+msgid "password is required"
+msgstr ""
+
+#: forum/utils/forms.py:137
+msgid "retype password"
+msgstr ""
+
+#: forum/utils/forms.py:138
+msgid "please, retype your password"
+msgstr ""
+
+#: forum/utils/forms.py:139
+msgid "sorry, entered passwords did not match, please try again"
+msgstr ""
+
+#: forum/views/admin.py:47
+#, python-format
+msgid "'%s' settings saved succesfully"
+msgstr ""
+
+#: forum/views/admin.py:141
+msgid "Bootstrap mode enabled"
+msgstr ""
+
+#: forum/views/admin.py:155
+msgid "All values reverted to defaults"
+msgstr ""
+
+#: forum/views/admin.py:171
+msgid "All values recalculated"
+msgstr ""
+
+#: forum/views/auth.py:103 forum/views/auth.py:112
+msgid ""
+"Sorry, these login credentials belong to anoother user. Plese terminate your "
+"current session and try again."
+msgstr ""
+
+#: forum/views/auth.py:105
+msgid "You are already logged in with that user."
+msgstr ""
+
+#: forum/views/auth.py:110
+msgid "These login credentials are already associated with your account."
+msgstr ""
+
+#: forum/views/auth.py:116
+msgid "The new credentials are now associated with your account"
+msgstr ""
+
+#: forum/views/auth.py:157
+msgid ""
+"Oops, something went wrong in the middle of this process. Please try again."
+msgstr ""
+
+#: forum/views/auth.py:219
+msgid "Temporary login link"
+msgstr ""
+
+#: forum/views/auth.py:224
+msgid "An email has been sent with your temporary login key"
+msgstr ""
+
+#: forum/views/auth.py:239
+msgid ""
+"You are logged in with a temporary access key, please take the time to fix "
+"your issue with authentication."
+msgstr ""
+
+#: forum/views/auth.py:245
+msgid "Email Validation"
+msgstr ""
+
+#: forum/views/auth.py:256
+msgid "Thank you, your email is now validated."
+msgstr ""
+
+#: forum/views/auth.py:280
+msgid "Your password was changed"
+msgstr ""
+
+#: forum/views/auth.py:282
+msgid "New password set"
+msgstr ""
+
+#: forum/views/auth.py:315
+#, python-format
+msgid "You removed the association with %s"
+msgstr ""
+
+#: forum/views/auth.py:353
+#, python-format
+msgid "Welcome back %s, you are now logged in"
+msgstr ""
+
+#: forum/views/commands.py:20
+#, python-format
+msgid ""
+"\n"
+"            Sorry, but you don't have enough reputation points to %(action)s."
+"<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:29
+#, python-format
+msgid ""
+"\n"
+"            Sorry but you cannot %(action)s your own post.<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:38
+#, python-format
+msgid ""
+"\n"
+"            Sorry but anonymous users cannot %(action)s.<br />\n"
+"            Please login or create an account <a href'%(signin_url)s'>here</"
+"a>.\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:47
+#, python-format
+msgid ""
+"\n"
+"            Sorry, but you don't have enough %(action)s left for today..<br /"
+">\n"
+"            The limit is %(limit)s per day..<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:57
+#, python-format
+msgid ""
+"\n"
+"            Sorry, but you cannot %(action)s twice the same post.<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:71 forum/views/commands.py:74
+#: forum/views/commands.py:111
+msgid "vote"
+msgid_plural "votes"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/views/commands.py:89
+#, python-format
+msgid ""
+"Sorry but you cannot cancel a vote after %(ndays)d %(tdays)s from the "
+"original vote"
+msgstr ""
+
+#: forum/views/commands.py:90
+msgid "day"
+msgid_plural "days"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/views/commands.py:110
+#, python-format
+msgid "You have %(nvotes)s %(tvotes)s left today."
+msgstr ""
+
+#: forum/views/commands.py:121 forum/views/commands.py:127
+msgid "flag posts"
+msgstr ""
+
+#: forum/views/commands.py:132
+msgid "flags"
+msgstr ""
+
+#: forum/views/commands.py:149 forum/views/commands.py:155
+msgid "like comments"
+msgstr ""
+
+#: forum/views/commands.py:152
+msgid "like"
+msgstr ""
+
+#: forum/views/commands.py:179 forum/views/commands.py:182
+msgid "delete comments"
+msgstr ""
+
+#: forum/views/commands.py:197
+msgid "mark a question as favorite"
+msgstr ""
+
+#: forum/views/commands.py:221 forum/views/commands.py:233
+msgid "comment"
+msgstr ""
+
+#: forum/views/commands.py:224 forum/views/commands.py:351
+msgid "Invalid request"
+msgstr ""
+
+#: forum/views/commands.py:230
+msgid "edit comments"
+msgstr ""
+
+#: forum/views/commands.py:240
+msgid "Comment is empty"
+msgstr ""
+
+#: forum/views/commands.py:265
+msgid "accept answers"
+msgstr ""
+
+#: forum/views/commands.py:271
+msgid "Sorry but only the question author can accept an answer"
+msgstr ""
+
+#: forum/views/commands.py:295 forum/views/commands.py:298
+msgid "delete posts"
+msgstr ""
+
+#: forum/views/meta.py:43
+#, python-format
+msgid "Feedback message from %(site_name)s"
+msgstr ""
+
+#: forum/views/meta.py:46
+msgid "Thanks for the feedback!"
+msgstr ""
+
+#: forum/views/meta.py:53
+msgid "We look forward to hearing your feedback! Please, give it next time :)"
+msgstr ""
+
+#: forum/views/readers.py:64
+msgid "Open questions without an accepted answer"
+msgstr ""
+
+#: forum/views/readers.py:73
+#, python-format
+msgid "Questions tagged <span class=\"tag\">%(tag)s</span>"
+msgstr ""
+
+#: forum/views/readers.py:131
+#, python-format
+msgid "questions matching '%(keywords)s'"
+msgstr ""
+
+#: forum/views/users.py:152
+msgid "user profile"
+msgstr ""
+
+#: forum/views/users.py:152
+msgid "user profile overview"
+msgstr ""
+
+#: forum/views/users.py:186
+msgid "recent user activity"
+msgstr ""
+
+#: forum/views/users.py:186
+msgid "profile - recent activity"
+msgstr ""
+
+#: forum/views/users.py:196
+msgid "profile - votes"
+msgstr ""
+
+#: forum/views/users.py:203
+msgid "user reputation in the community"
+msgstr ""
+
+#: forum/views/users.py:203
+msgid "profile - user reputation"
+msgstr ""
+
+#: forum/views/users.py:214
+msgid "favorite questions"
+msgstr ""
+
+#: forum/views/users.py:214
+msgid "profile - favorite questions"
+msgstr ""
+
+#: forum/views/users.py:220
+msgid "subscription settings"
+msgstr ""
+
+#: forum/views/users.py:220
+msgid "profile - subscriptions"
+msgstr ""
+
+#: forum/views/users.py:230
+msgid "Notifications are now enabled"
+msgstr ""
+
+#: forum/views/users.py:232
+msgid "Notifications are now disabled"
+msgstr ""
+
+#: forum/views/users.py:239
+msgid "New subscription settings are now saved"
+msgstr ""
+
+#: forum/views/writers.py:68
+msgid "uploading images is limited to users with >60 reputation points"
+msgstr ""
+
+#: forum/views/writers.py:70
+msgid "allowed file types are 'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'"
+msgstr ""
+
+#: forum/views/writers.py:72
+#, python-format
+msgid "maximum upload file size is %sM"
+msgstr ""
+
+#: forum/views/writers.py:74
+#, python-format
+msgid ""
+"Error uploading file. Please contact the site administrator. Thank you. %s"
+msgstr ""
+
+#: forum/views/writers.py:85
+msgid "Initial revision"
+msgstr ""
+
+#: forum/views/writers.py:143
+msgid "Retag"
+msgstr ""
+
+#: forum_modules/books/urls.py:7 forum_modules/books/urls.py:8
+#: forum_modules/books/urls.py:9
+msgid "books/"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:17
+#: forum_modules/default_badges/badges.py:24
+#: forum_modules/default_badges/badges.py:31
+#, python-format
+msgid "Asked a question with %s views"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:39
+#: forum_modules/default_badges/badges.py:53
+#: forum_modules/default_badges/badges.py:67
+#, python-format
+msgid "Answer voted up %s times"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:46
+#: forum_modules/default_badges/badges.py:60
+#: forum_modules/default_badges/badges.py:74
+#, python-format
+msgid "Question voted up %s times"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:82
+#: forum_modules/default_badges/badges.py:89
+#, python-format
+msgid "Question favorited by %s users"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:97
+#, python-format
+msgid "Deleted own post with score of %s or higher"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:108
+#, python-format
+msgid "Deleted own post with score of %s or lower"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:120
+msgid "First flagged post"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:127
+msgid "First down vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:134
+msgid "First retag"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:141
+msgid "First up vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:148
+msgid "First edit"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:155
+msgid "First accepted answer on your own question"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:162
+msgid "Completed all user profile fields"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:169
+msgid "First rollback"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:177
+#, python-format
+msgid "Voted %s times"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:184
+#, python-format
+msgid "Left %s comments"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:192
+#, python-format
+msgid "Answered your own question with at least %s up votes"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:205
+msgid "Strunk & White"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:206
+#, python-format
+msgid "Edited %s entries"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:217
+msgid "Asked first question with at least one up vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:228
+msgid "Answered first question with at least one up vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:260
+#, python-format
+msgid "First answer was accepted with at least %s up votes"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:271
+#, python-format
+msgid "Accepted answer and voted up %s times"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:282
+#, python-format
+msgid ""
+"Answered a question more than %(dif_days)s days later with at least %"
+"(up_votes)s votes"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:295
+#, python-format
+msgid "Created a tag used by %s questions"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:6
+msgid "Popular Question views"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:7
+msgid ""
+"\n"
+"Number of question views required to award a Popular Question badge to the "
+"question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:12
+msgid "Notable Question views"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:13
+msgid ""
+"\n"
+"Number of question views required to award a Notable Question badge to the "
+"question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:18
+msgid "Famous Question views"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:19
+msgid ""
+"\n"
+"Number of question views required to award a Famous Question badge to the "
+"question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:24
+msgid "Nice Answer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:25
+msgid ""
+"\n"
+"Number of up votes required to award a Nice Answer badge to the answer "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:30
+msgid "Nice Question up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:31
+msgid ""
+"\n"
+"Number of up votes required to award a Nice Question badge to the question "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:36
+msgid "Good Answer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:37
+msgid ""
+"\n"
+"Number of up votes required to award a Good Answer badge to the answer "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:42
+msgid "Good Question up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:43
+msgid ""
+"\n"
+"Number of up votes required to award a Good Question badge to the question "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:48
+msgid "Great Answer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:49
+msgid ""
+"\n"
+"Number of up votes required to award a Great Answer badge to the answer "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:54
+msgid "Great Question up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:55
+msgid ""
+"\n"
+"Number of up votes required to award a Great Question badge to the question "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:60
+msgid "Favorite Question favorite count"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:61
+msgid ""
+"\n"
+"How many times a question needs to be favorited by other users to award a "
+"Favorite Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:66
+msgid "Stellar Question favorite count"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:67
+msgid ""
+"\n"
+"How many times a question needs to be favorited by other users to award a "
+"Stellar Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:72
+msgid "Disciplined minimum score"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:73
+msgid ""
+"\n"
+"Minimum score a question needs to have to award the Disciplined badge to an "
+"author of a question who deletes it.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:78
+msgid "Peer Pressure maximum score"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:79
+msgid ""
+"\n"
+"Maximum score a question needs to have to award the Peer Pressure badge to "
+"an author of a question who deletes it.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:84
+msgid "Civic Duty votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:85
+msgid ""
+"\n"
+"Number of votes an user needs to cast to be awarded the Civic Duty badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:90
+msgid "Pundit number of comments"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:91
+msgid ""
+"\n"
+"Number of comments an user needs to post to be awarded the Pundit badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:96
+msgid "Self Learner up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:97
+msgid ""
+"\n"
+"Number of up votes an answer from the question author needs to have for the "
+"author to be awarded the Self Learner badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:102
+msgid "Strunk and White updates"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:103
+msgid ""
+"\n"
+"Number of question or answer updates an user needs to make to be awarded the "
+"Strunk & White badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:108
+msgid "Enlightened up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:109
+msgid ""
+"\n"
+"Number of up votes an accepted answer needs to have for the author to be "
+"awarded the Enlightened badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:114
+msgid "Guru up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:115
+msgid ""
+"\n"
+"Number of up votes an accepted answer needs to have for the author to be "
+"awarded the Guru badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:120
+msgid "Necromancer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:121
+msgid ""
+"\n"
+"Number of up votes an answer needs to have for the author to be awarded the "
+"Necromancer badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:126
+msgid "Necromancer difference in days"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:127
+msgid ""
+"\n"
+"Difference in days betwen the posted date of a question and an answer for "
+"the answer author to be awarded the Necromancer badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:132
+msgid "Taxonomist usage count"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:133
+msgid ""
+"\n"
+"How many usages a tag needs to have for the tag creator to be awarded the "
+"Taxonomist badge. \n"
+msgstr ""
+
+#: forum_modules/facebookauth/authentication.py:31
+msgid "Sorry, your Facebook session has expired, please try again"
+msgstr ""
+
+#: forum_modules/facebookauth/authentication.py:33
+msgid ""
+"The authentication with Facebook connect failed due to an invalid signature"
+msgstr ""
+
+#: forum_modules/facebookauth/authentication.py:35
+msgid ""
+"The authentication with Facebook connect failed, cannot find authentication "
+"tokens"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:75
+msgid "Please enter valid username and password (both are case-sensitive)."
+msgstr ""
+
+#: forum_modules/localauth/forms.py:79
+msgid "This account is inactive."
+msgstr ""
+
+#: forum_modules/localauth/forms.py:81
+msgid "Login failed."
+msgstr ""
+
+#: forum_modules/localauth/forms.py:85
+msgid "This user is not a valid user"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:88
+msgid "Please enter username and password"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:90
+msgid "Please enter your password"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:92
+msgid "Please enter user name"
+msgstr ""
+
+#: forum_modules/localauth/urls.py:7
+msgid "local/"
+msgstr ""
+
+#: forum_modules/localauth/views.py:33
+msgid "A validation email has been sent to your email address. "
+msgstr ""
+
+#: forum_modules/oauthauth/consumer.py:33
+msgid "Error, the oauth token is not on the server"
+msgstr ""
+
+#: forum_modules/oauthauth/consumer.py:38
+msgid "Something went wrong! Auth tokens do not match"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:40
+msgid "Sorry, but your input is not a valid OpenId"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:92
+msgid "The OpenId authentication request was canceled"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:94
+msgid "The OpenId authentication failed: "
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:96
+msgid "Setup needed"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:98
+msgid "The OpenId authentication failed with an unknown status: "
+msgstr ""
+
+#: forum_modules/openidauth/templates/openidurl.html:7
+msgid "Enter your OpenId Url"
+msgstr ""
+
+#: forum_modules/project_badges/badges.py:9
+#, python-format
+msgid "Got %s upvotes in a question tagged with \"bug\""
+msgstr ""
+
+#: forum_modules/recaptcha/formfield.py:20
+msgid "Invalid captcha"
+msgstr ""
+
+#: forum_modules/sximporter/importer.py:39
+#, python-format
+msgid "Unknown user %(number)d"
+msgstr ""
+
+#: forum_modules/sximporter/urls.py:8
+msgid "sximporter/"
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:7
+msgid "SX Importer"
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:10
+msgid "Welcome to Stack Exchange dump importer."
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:16
+msgid "Your user id in stack exchange"
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:20
+msgid "Merge users with same user name and email"
+msgstr ""
+
+#: locale/phrases.py:1
+msgid "Test Phrase 1"
+msgstr ""
+
+#: locale/phrases.py:2
+msgid "Test Phrase 2"
+msgstr ""
+
+#: locale/phrases.py:3
+msgid "Test Phrase 3"
+msgstr ""
+
+#: locale/phrases.py:4
+msgid "Test Phrase n"
+msgstr ""
diff --git a/forum/modules/template_loader.py/locale/l/LC_MESSAGES/django.mo b/forum/modules/template_loader.py/locale/l/LC_MESSAGES/django.mo
new file mode 100644 (file)
index 0000000..345109f
Binary files /dev/null and b/forum/modules/template_loader.py/locale/l/LC_MESSAGES/django.mo differ
diff --git a/forum/modules/template_loader.py/locale/l/LC_MESSAGES/django.po b/forum/modules/template_loader.py/locale/l/LC_MESSAGES/django.po
new file mode 100644 (file)
index 0000000..7a76e84
--- /dev/null
@@ -0,0 +1,4446 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-04-28 16:53-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"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: forum/const.py:8
+msgid "duplicate question"
+msgstr ""
+
+#: forum/const.py:9
+msgid "question is off-topic or not relevant"
+msgstr ""
+
+#: forum/const.py:10
+msgid "too subjective and argumentative"
+msgstr ""
+
+#: forum/const.py:11
+msgid "is not an answer to the question"
+msgstr ""
+
+#: forum/const.py:12
+msgid "the question is answered, right answer was accepted"
+msgstr ""
+
+#: forum/const.py:13
+msgid "problem is not reproducible or outdated"
+msgstr ""
+
+#: forum/const.py:14
+msgid "question contains offensive inappropriate, or malicious remarks"
+msgstr ""
+
+#: forum/const.py:15
+msgid "spam or advertising"
+msgstr ""
+
+#: forum/const.py:71 forum/skins/default/templates/osqaadmin/index.html:21
+msgid "question"
+msgstr ""
+
+#: forum/const.py:72 forum/skins/default/templates/book.html:110
+#: forum/skins/default/templates/osqaadmin/index.html:26
+msgid "answer"
+msgstr ""
+
+#: forum/const.py:73
+msgid "commented question"
+msgstr ""
+
+#: forum/const.py:74
+msgid "commented answer"
+msgstr ""
+
+#: forum/const.py:75
+msgid "edited question"
+msgstr ""
+
+#: forum/const.py:76
+msgid "edited answer"
+msgstr ""
+
+#: forum/const.py:77
+msgid "received award"
+msgstr ""
+
+#: forum/const.py:78
+msgid "marked best answer"
+msgstr ""
+
+#: forum/const.py:79
+msgid "upvoted"
+msgstr ""
+
+#: forum/const.py:80
+msgid "downvoted"
+msgstr ""
+
+#: forum/const.py:81
+msgid "upvote canceled"
+msgstr ""
+
+#: forum/const.py:82
+msgid "downvote canceled"
+msgstr ""
+
+#: forum/const.py:83
+msgid "deleted question"
+msgstr ""
+
+#: forum/const.py:84
+msgid "deleted answer"
+msgstr ""
+
+#: forum/const.py:85
+msgid "marked offensive"
+msgstr ""
+
+#: forum/const.py:86
+msgid "updated tags"
+msgstr ""
+
+#: forum/const.py:87
+msgid "selected favorite"
+msgstr ""
+
+#: forum/const.py:88
+msgid "completed user profile"
+msgstr ""
+
+#: forum/const.py:89
+msgid "email update sent to user"
+msgstr ""
+
+#: forum/const.py:93
+msgid "question_answered"
+msgstr ""
+
+#: forum/const.py:94
+msgid "question_commented"
+msgstr ""
+
+#: forum/const.py:95
+msgid "answer_commented"
+msgstr ""
+
+#: forum/const.py:96
+msgid "answer_accepted"
+msgstr ""
+
+#: forum/const.py:100
+msgid "[closed]"
+msgstr ""
+
+#: forum/const.py:101
+msgid "[deleted]"
+msgstr ""
+
+#: forum/const.py:102
+msgid "initial version"
+msgstr ""
+
+#: forum/const.py:103
+msgid "retagged"
+msgstr ""
+
+#: forum/const.py:111
+msgid "Instantly"
+msgstr ""
+
+#: forum/const.py:112
+msgid "Daily"
+msgstr ""
+
+#: forum/const.py:113
+msgid "Weekly"
+msgstr ""
+
+#: forum/const.py:114
+msgid "No notifications"
+msgstr ""
+
+#: forum/feed.py:18
+msgid " - "
+msgstr ""
+
+#: forum/feed.py:18
+msgid "latest questions"
+msgstr ""
+
+#: forum/forms.py:21 forum/skins/default/templates/answer_edit_tips.html:35
+#: forum/skins/default/templates/answer_edit_tips.html:39
+#: forum/skins/default/templates/question_edit_tips.html:37
+#: forum/skins/default/templates/question_edit_tips.html:42
+msgid "title"
+msgstr ""
+
+#: forum/forms.py:22
+msgid "please enter a descriptive title for your question"
+msgstr ""
+
+#: forum/forms.py:27
+msgid "title must be > 10 characters"
+msgstr ""
+
+#: forum/forms.py:36
+msgid "content"
+msgstr ""
+
+#: forum/forms.py:42
+msgid "question content must be > 10 characters"
+msgstr ""
+
+#: forum/forms.py:52 forum/skins/default/templates/header.html:31
+#: forum/skins/default/templates/header.html:56
+msgid "tags"
+msgstr ""
+
+#: forum/forms.py:54
+msgid ""
+"Tags are short keywords, with no spaces within. Up to five tags can be used."
+msgstr ""
+
+#: forum/forms.py:61 forum/skins/default/templates/question_retag.html:43
+msgid "tags are required"
+msgstr ""
+
+#: forum/forms.py:67
+msgid "please use 5 tags or less"
+msgstr ""
+
+#: forum/forms.py:72
+msgid "tags must be shorter than 20 characters"
+msgstr ""
+
+#: forum/forms.py:74
+msgid ""
+"please use following characters in tags: letters 'a-z', numbers, and "
+"characters '.-_#'"
+msgstr ""
+
+#: forum/forms.py:84
+#: forum/skins/default/templates/post_contributor_info.html:7
+#: forum/skins/default/templates/question_summary_list_roll.html:26
+#: forum/skins/default/templates/question_summary_list_roll.html:38
+msgid "community wiki"
+msgstr ""
+
+#: forum/forms.py:85
+msgid ""
+"if you choose community wiki option, the question and answer do not generate "
+"points and name of author will not be shown"
+msgstr ""
+
+#: forum/forms.py:101
+msgid "update summary:"
+msgstr ""
+
+#: forum/forms.py:102
+msgid ""
+"enter a brief summary of your revision (e.g. fixed spelling, grammar, "
+"improved style, this field is optional)"
+msgstr ""
+
+#: forum/forms.py:105
+msgid "Automatically accept user's contributions for the email updates"
+msgstr ""
+
+#: forum/forms.py:118
+msgid "Your name:"
+msgstr ""
+
+#: forum/forms.py:119
+msgid "Email (not shared with anyone):"
+msgstr ""
+
+#: forum/forms.py:120
+msgid "Your message:"
+msgstr ""
+
+#: forum/forms.py:202
+msgid "this email does not have to be linked to gravatar"
+msgstr ""
+
+#: forum/forms.py:204
+msgid "Screen name"
+msgstr ""
+
+#: forum/forms.py:205
+msgid "Real name"
+msgstr ""
+
+#: forum/forms.py:206
+msgid "Website"
+msgstr ""
+
+#: forum/forms.py:207
+msgid "Location"
+msgstr ""
+
+#: forum/forms.py:208
+msgid "Date of birth"
+msgstr ""
+
+#: forum/forms.py:208
+msgid "will not be shown, used to calculate age, format: YYYY-MM-DD"
+msgstr ""
+
+#: forum/forms.py:209 forum/skins/default/templates/account_settings.html:21
+msgid "Profile"
+msgstr ""
+
+#: forum/forms.py:240 forum/forms.py:241
+msgid "this email has already been registered, please use another one"
+msgstr ""
+
+#: forum/subscriptions.py:41
+#, python-format
+msgid "New question on %(app_name)s"
+msgstr ""
+
+#: forum/subscriptions.py:73
+#, python-format
+msgid "New answer to '%(question_title)s'"
+msgstr ""
+
+#: forum/subscriptions.py:112
+#, python-format
+msgid "New comment on %(question_title)s"
+msgstr ""
+
+#: forum/subscriptions.py:136
+#, python-format
+msgid "An answer to '%(question_title)s' was accepted"
+msgstr ""
+
+#: forum/subscriptions.py:156
+#, python-format
+msgid "%(username)s is a new member on %(app_name)s"
+msgstr ""
+
+#: forum/urls.py:44
+msgid "upfiles/"
+msgstr ""
+
+#: forum/urls.py:49
+msgid "about/"
+msgstr ""
+
+#: forum/urls.py:50
+msgid "faq/"
+msgstr ""
+
+#: forum/urls.py:51
+msgid "privacy/"
+msgstr ""
+
+#: forum/urls.py:52
+msgid "logout/"
+msgstr ""
+
+#: forum/urls.py:53 forum/urls.py:54
+msgid "answers/"
+msgstr ""
+
+#: forum/urls.py:53 forum/urls.py:58 forum/urls.py:98
+#: forum/skins/default/templates/users/info.html:44
+msgid "edit/"
+msgstr ""
+
+#: forum/urls.py:54 forum/urls.py:74
+msgid "revisions/"
+msgstr ""
+
+#: forum/urls.py:55 forum/urls.py:56 forum/urls.py:57 forum/urls.py:58
+#: forum/urls.py:59 forum/urls.py:60 forum/urls.py:61 forum/urls.py:74
+msgid "questions/"
+msgstr ""
+
+#: forum/urls.py:56 forum_modules/books/urls.py:8
+msgid "ask/"
+msgstr ""
+
+#: forum/urls.py:57
+msgid "unanswered/"
+msgstr ""
+
+#: forum/urls.py:59
+msgid "close/"
+msgstr ""
+
+#: forum/urls.py:60
+msgid "reopen/"
+msgstr ""
+
+#: forum/urls.py:61
+msgid "answer/"
+msgstr ""
+
+#: forum/urls.py:63
+msgid "vote/"
+msgstr ""
+
+#: forum/urls.py:64
+msgid "like_comment/"
+msgstr ""
+
+#: forum/urls.py:65
+msgid "comment/"
+msgstr ""
+
+#: forum/urls.py:66
+msgid "delete_comment/"
+msgstr ""
+
+#: forum/urls.py:67
+msgid "accept_answer/"
+msgstr ""
+
+#: forum/urls.py:68
+msgid "mark_favorite/"
+msgstr ""
+
+#: forum/urls.py:69
+msgid "flag/"
+msgstr ""
+
+#: forum/urls.py:70
+msgid "delete/"
+msgstr ""
+
+#: forum/urls.py:71
+msgid "subscribe/"
+msgstr ""
+
+#: forum/urls.py:72
+msgid "matching_tags/"
+msgstr ""
+
+#: forum/urls.py:75
+msgid "command/"
+msgstr ""
+
+#: forum/urls.py:78
+msgid "question/"
+msgstr ""
+
+#: forum/urls.py:79 forum/urls.py:80
+msgid "tags/"
+msgstr ""
+
+#: forum/urls.py:82 forum/urls.py:86
+msgid "mark-tag/"
+msgstr ""
+
+#: forum/urls.py:82
+msgid "interesting/"
+msgstr ""
+
+#: forum/urls.py:86
+msgid "ignored/"
+msgstr ""
+
+#: forum/urls.py:90
+msgid "unmark-tag/"
+msgstr ""
+
+#: forum/urls.py:96 forum/urls.py:98 forum/urls.py:100 forum/urls.py:101
+#: forum/urls.py:102 forum/urls.py:103 forum/urls.py:104 forum/urls.py:105
+#: forum/models/user.py:124
+msgid "users/"
+msgstr ""
+
+#: forum/urls.py:97
+msgid "moderate-user/"
+msgstr ""
+
+#: forum/urls.py:100
+msgid "subscriptions/"
+msgstr ""
+
+#: forum/urls.py:101
+msgid "favorites/"
+msgstr ""
+
+#: forum/urls.py:102
+msgid "reputation/"
+msgstr ""
+
+#: forum/urls.py:103
+msgid "votes/"
+msgstr ""
+
+#: forum/urls.py:104
+msgid "recent/"
+msgstr ""
+
+#: forum/urls.py:107 forum/urls.py:108
+msgid "badges/"
+msgstr ""
+
+#: forum/urls.py:109
+msgid "messages/"
+msgstr ""
+
+#: forum/urls.py:109
+msgid "markread/"
+msgstr ""
+
+#: forum/urls.py:111
+msgid "nimda/"
+msgstr ""
+
+#: forum/urls.py:113
+msgid "upload/"
+msgstr ""
+
+#: forum/urls.py:114
+msgid "search/"
+msgstr ""
+
+#: forum/urls.py:115
+msgid "feedback/"
+msgstr ""
+
+#: forum/urls.py:119 forum/urls.py:120 forum/urls.py:121 forum/urls.py:122
+#: forum/urls.py:123 forum/urls.py:124 forum/urls.py:125 forum/urls.py:126
+#: forum/urls.py:127 forum/urls.py:128 forum/urls.py:129 forum/urls.py:130
+#: forum_modules/localauth/urls.py:7
+msgid "account/"
+msgstr ""
+
+#: forum/urls.py:119 forum/urls.py:121 forum/urls.py:122
+msgid "signin/"
+msgstr ""
+
+#: forum/urls.py:120
+msgid "signout/"
+msgstr ""
+
+#: forum/urls.py:123
+msgid "done/"
+msgstr ""
+
+#: forum/urls.py:124 forum_modules/localauth/urls.py:7
+msgid "register/"
+msgstr ""
+
+#: forum/urls.py:125
+msgid "validate/"
+msgstr ""
+
+#: forum/urls.py:126 forum/urls.py:127
+msgid "tempsignin/"
+msgstr ""
+
+#: forum/urls.py:128
+msgid "authsettings/"
+msgstr ""
+
+#: forum/urls.py:129 forum/urls.py:130
+msgid "providers/"
+msgstr ""
+
+#: forum/urls.py:129
+msgid "remove/"
+msgstr ""
+
+#: forum/urls.py:130
+msgid "add/"
+msgstr ""
+
+#: forum/urls.py:133 forum/urls.py:134 forum/urls.py:135 forum/urls.py:136
+#: forum/urls.py:137 forum_modules/sximporter/urls.py:8
+msgid "admin/"
+msgstr ""
+
+#: forum/urls.py:134
+msgid "denormalize/"
+msgstr ""
+
+#: forum/urls.py:135
+msgid "go_bootstrap/"
+msgstr ""
+
+#: forum/urls.py:136
+msgid "go_defaults/"
+msgstr ""
+
+#: forum/authentication/forms.py:21
+msgid "Your account email"
+msgstr ""
+
+#: forum/authentication/forms.py:23
+msgid "You cannot leave this field blank"
+msgstr ""
+
+#: forum/authentication/forms.py:24 forum/utils/forms.py:107
+msgid "please enter a valid email address"
+msgstr ""
+
+#: forum/authentication/forms.py:32
+msgid "Sorry, but this email is not on our database."
+msgstr ""
+
+#: forum/authentication/forms.py:40
+msgid "okay, let's try!"
+msgstr ""
+
+#: forum/authentication/forms.py:41
+msgid "no OSQA community email please, thanks"
+msgstr ""
+
+#: forum/authentication/forms.py:44
+msgid "please choose one of the options above"
+msgstr ""
+
+#: forum/authentication/forms.py:51
+msgid "Current password"
+msgstr ""
+
+#: forum/authentication/forms.py:62
+msgid ""
+"Old password is incorrect.                     Please enter the correct "
+"password."
+msgstr ""
+
+#: forum/management/commands/send_email_alerts.py:56
+msgid "Daily digest"
+msgstr ""
+
+#: forum/middleware/anon_user.py:34
+#, python-format
+msgid "First time here? Check out the <a href=\"%s\">FAQ</a>!"
+msgstr ""
+
+#: forum/models/question.py:30
+msgid "[closed] "
+msgstr ""
+
+#: forum/models/question.py:33
+msgid "[deleted] "
+msgstr ""
+
+#: forum/models/repute.py:13 forum/skins/default/templates/badges.html:53
+msgid "gold"
+msgstr ""
+
+#: forum/models/repute.py:14 forum/skins/default/templates/badges.html:61
+msgid "silver"
+msgstr ""
+
+#: forum/models/repute.py:15 forum/skins/default/templates/badges.html:68
+msgid "bronze"
+msgstr ""
+
+#: forum/models/tag.py:28
+msgid "interesting"
+msgstr ""
+
+#: forum/models/tag.py:28
+msgid "ignored"
+msgstr ""
+
+#: forum/models/user.py:255
+#: forum/skins/default/templates/post_contributor_info.html:19
+msgid "asked"
+msgstr ""
+
+#: forum/models/user.py:257
+#: forum/skins/default/templates/post_contributor_info.html:22
+msgid "answered"
+msgstr ""
+
+#: forum/models/user.py:259
+msgid "marked an answer"
+msgstr ""
+
+#: forum/models/user.py:261
+msgid "edited a question"
+msgstr ""
+
+#: forum/models/user.py:263
+msgid "commented a question"
+msgstr ""
+
+#: forum/models/user.py:265
+msgid "commented an answer"
+msgstr ""
+
+#: forum/models/user.py:267
+msgid "edited an answer"
+msgstr ""
+
+#: forum/models/user.py:269
+msgid "received badge"
+msgstr ""
+
+#: forum/settings/__init__.py:20
+msgid "Badges config"
+msgstr ""
+
+#: forum/settings/__init__.py:20
+msgid "Configure badges on your OSQA site."
+msgstr ""
+
+#: forum/settings/basic.py:9
+msgid "Basic Settings"
+msgstr ""
+
+#: forum/settings/basic.py:9
+msgid "The basic settings for your application"
+msgstr ""
+
+#: forum/settings/basic.py:12
+msgid "Application logo"
+msgstr ""
+
+#: forum/settings/basic.py:13
+msgid "Your site main logo."
+msgstr ""
+
+#: forum/settings/basic.py:17
+msgid "Favicon"
+msgstr ""
+
+#: forum/settings/basic.py:18
+msgid "Your site favicon."
+msgstr ""
+
+#: forum/settings/basic.py:22
+msgid "Application title"
+msgstr ""
+
+#: forum/settings/basic.py:23
+msgid "The title of your application that will show in the browsers title bar"
+msgstr ""
+
+#: forum/settings/basic.py:26
+msgid "Application short name"
+msgstr ""
+
+#: forum/settings/basic.py:30
+msgid "Application keywords"
+msgstr ""
+
+#: forum/settings/basic.py:31
+msgid "The meta keywords that will be available through the HTML meta tags."
+msgstr ""
+
+#: forum/settings/basic.py:34
+msgid "Application description"
+msgstr ""
+
+#: forum/settings/basic.py:35
+msgid "The description of your application"
+msgstr ""
+
+#: forum/settings/basic.py:39
+msgid "Application intro"
+msgstr ""
+
+#: forum/settings/basic.py:40
+msgid ""
+"The introductory page that is visible in the sidebar for anonymous users."
+msgstr ""
+
+#: forum/settings/basic.py:44
+msgid "Copyright notice"
+msgstr ""
+
+#: forum/settings/basic.py:45
+msgid "The copyright notice visible at the footer of your page."
+msgstr ""
+
+#: forum/settings/basic.py:48
+msgid "Maximum length of comment"
+msgstr ""
+
+#: forum/settings/basic.py:49
+msgid "The maximum length a user can enter for a comment."
+msgstr ""
+
+#: forum/settings/email.py:5
+msgid "Email Settings"
+msgstr ""
+
+#: forum/settings/email.py:5
+msgid "Email server and other email related settings."
+msgstr ""
+
+#: forum/settings/email.py:8
+msgid "Email Server"
+msgstr ""
+
+#: forum/settings/email.py:9
+msgid "The SMTP server through which your application will be sending emails."
+msgstr ""
+
+#: forum/settings/email.py:13
+msgid "Email Port"
+msgstr ""
+
+#: forum/settings/email.py:14
+msgid ""
+"The port on which your SMTP server is listening to. Usually this is 25, but "
+"can be something else."
+msgstr ""
+
+#: forum/settings/email.py:18
+msgid "Email User"
+msgstr ""
+
+#: forum/settings/email.py:19
+msgid "The username for your SMTP connection."
+msgstr ""
+
+#: forum/settings/email.py:23
+msgid "Email Password"
+msgstr ""
+
+#: forum/settings/email.py:24
+msgid "The password for your SMTP connection."
+msgstr ""
+
+#: forum/settings/email.py:29
+msgid "Use TLS"
+msgstr ""
+
+#: forum/settings/email.py:30
+msgid "Does your SMTP server usFes TLS for authentication."
+msgstr ""
+
+#: forum/settings/email.py:34
+msgid "Site 'from' email address"
+msgstr ""
+
+#: forum/settings/email.py:35
+msgid ""
+"The address that will show up on the 'from' field on emails sent by your "
+"website."
+msgstr ""
+
+#: forum/settings/email.py:39
+msgid "Email subject prefix"
+msgstr ""
+
+#: forum/settings/email.py:40
+msgid ""
+"Every email sent through your website will have the subject prefixed by this "
+"string. It's usually a good idea to have such a prefix so your users can "
+"easilly set up a filter on their email clients."
+msgstr ""
+
+#: forum/settings/extkeys.py:4
+msgid "External Keys"
+msgstr ""
+
+#: forum/settings/extkeys.py:4
+msgid ""
+"Keys for various external providers that your application may optionally use."
+msgstr ""
+
+#: forum/settings/extkeys.py:7
+msgid "Google sitemap code"
+msgstr ""
+
+#: forum/settings/extkeys.py:8
+msgid ""
+"This is the code you get when you register your site at <a href='https://www."
+"google.com/webmasters/tools/'>Google webmaster central</a>."
+msgstr ""
+
+#: forum/settings/extkeys.py:12
+msgid "Google analytics key"
+msgstr ""
+
+#: forum/settings/extkeys.py:13
+msgid ""
+"Your Google analytics key. You can get one at the <a href='http://www.google."
+"com/analytics/'>Google analytics official website</a>"
+msgstr ""
+
+#: forum/settings/forms.py:40
+msgid "Change this:"
+msgstr ""
+
+#: forum/settings/minrep.py:4
+msgid "Minimum reputation config"
+msgstr ""
+
+#: forum/settings/minrep.py:4
+msgid ""
+"Configure the minimum reputation required to perform certain actions on your "
+"site."
+msgstr ""
+
+#: forum/settings/minrep.py:7
+msgid "Minimum reputation to vote up"
+msgstr ""
+
+#: forum/settings/minrep.py:8
+msgid "The minimum reputation an user must have to be allowed to vote up."
+msgstr ""
+
+#: forum/settings/minrep.py:11
+msgid "Minimum reputation to vote down"
+msgstr ""
+
+#: forum/settings/minrep.py:12
+msgid "The minimum reputation an user must have to be allowed to vote down."
+msgstr ""
+
+#: forum/settings/minrep.py:15
+msgid "Minimum reputation to flag a post"
+msgstr ""
+
+#: forum/settings/minrep.py:16
+msgid "The minimum reputation an user must have to be allowed to flag a post."
+msgstr ""
+
+#: forum/settings/minrep.py:19
+msgid "Minimum reputation to comment"
+msgstr ""
+
+#: forum/settings/minrep.py:20
+msgid ""
+"The minimum reputation an user must have to be allowed to comment a post."
+msgstr ""
+
+#: forum/settings/minrep.py:23
+msgid "Minimum reputation to like a comment"
+msgstr ""
+
+#: forum/settings/minrep.py:24
+msgid ""
+"The minimum reputation an user must have to be allowed to \"like\" a comment."
+msgstr ""
+
+#: forum/settings/minrep.py:27
+msgid "Minimum reputation to upload"
+msgstr ""
+
+#: forum/settings/minrep.py:28
+msgid ""
+"The minimum reputation an user must have to be allowed to upload a file."
+msgstr ""
+
+#: forum/settings/minrep.py:31
+msgid "Minimum reputation to close own question"
+msgstr ""
+
+#: forum/settings/minrep.py:32
+msgid ""
+"The minimum reputation an user must have to be allowed to close his own "
+"question."
+msgstr ""
+
+#: forum/settings/minrep.py:35
+msgid "Minimum reputation to reopen own question"
+msgstr ""
+
+#: forum/settings/minrep.py:36
+msgid ""
+"The minimum reputation an user must have to be allowed to reopen his own "
+"question."
+msgstr ""
+
+#: forum/settings/minrep.py:39
+msgid "Minimum reputation to retag others questions"
+msgstr ""
+
+#: forum/settings/minrep.py:40
+msgid ""
+"The minimum reputation an user must have to be allowed to retag others "
+"questions."
+msgstr ""
+
+#: forum/settings/minrep.py:43
+msgid "Minimum reputation to edit wiki posts"
+msgstr ""
+
+#: forum/settings/minrep.py:44
+msgid ""
+"The minimum reputation an user must have to be allowed to edit community "
+"wiki posts."
+msgstr ""
+
+#: forum/settings/minrep.py:47
+msgid "Minimum reputation to edit others posts"
+msgstr ""
+
+#: forum/settings/minrep.py:48
+msgid ""
+"The minimum reputation an user must have to be allowed to edit others posts."
+msgstr ""
+
+#: forum/settings/minrep.py:51
+msgid "Minimum reputation to close others posts"
+msgstr ""
+
+#: forum/settings/minrep.py:52
+msgid ""
+"The minimum reputation an user must have to be allowed to close others posts."
+msgstr ""
+
+#: forum/settings/minrep.py:55
+msgid "Minimum reputation to delete comments"
+msgstr ""
+
+#: forum/settings/minrep.py:56
+msgid ""
+"The minimum reputation an user must have to be allowed to delete comments."
+msgstr ""
+
+#: forum/settings/minrep.py:59
+msgid "Minimum reputation to view offensive flags"
+msgstr ""
+
+#: forum/settings/minrep.py:60
+msgid "The minimum reputation an user must have to view offensive flags."
+msgstr ""
+
+#: forum/settings/repgain.py:4
+msgid "Reputation gains and losses config"
+msgstr ""
+
+#: forum/settings/repgain.py:4
+msgid ""
+"Configure the reputation points a user may gain or lose upon certain actions."
+msgstr ""
+
+#: forum/settings/repgain.py:7
+msgid "Initial reputation"
+msgstr ""
+
+#: forum/settings/repgain.py:8
+msgid "The initial reputation an user gets when he first signs in."
+msgstr ""
+
+#: forum/settings/repgain.py:12
+msgid "Maximum reputation a user can gain in one day for being upvoted."
+msgstr ""
+
+#: forum/settings/repgain.py:15
+msgid "Rep gain by upvoted"
+msgstr ""
+
+#: forum/settings/repgain.py:16
+msgid "Reputation a user gains for having one of his posts up voted."
+msgstr ""
+
+#: forum/settings/repgain.py:19
+msgid "Rep lost bu upvote canceled"
+msgstr ""
+
+#: forum/settings/repgain.py:20
+msgid ""
+"Reputation a user loses for having one of the upvotes on his posts canceled."
+msgstr ""
+
+#: forum/settings/repgain.py:23
+msgid "Rep lost by downvoted"
+msgstr ""
+
+#: forum/settings/repgain.py:24
+msgid "Reputation a user loses for having one of his posts down voted."
+msgstr ""
+
+#: forum/settings/repgain.py:27
+msgid "Rep lost by downvoting"
+msgstr ""
+
+#: forum/settings/repgain.py:28
+msgid "Reputation a user loses for down voting a post."
+msgstr ""
+
+#: forum/settings/repgain.py:31
+msgid "Rep gain by downvote canceled"
+msgstr ""
+
+#: forum/settings/repgain.py:32
+msgid ""
+"Reputation a user gains for having one of the downvotes on his posts "
+"canceled."
+msgstr ""
+
+#: forum/settings/repgain.py:35
+msgid "Rep gain by canceling downvote"
+msgstr ""
+
+#: forum/settings/repgain.py:36
+msgid "Reputation a user gains for canceling a downvote."
+msgstr ""
+
+#: forum/settings/repgain.py:39
+msgid "Rep gain by accepted answer"
+msgstr ""
+
+#: forum/settings/repgain.py:40
+msgid "Reputation a user gains for having one of his answers accepted."
+msgstr ""
+
+#: forum/settings/repgain.py:43
+msgid "Rep lost by accepted canceled"
+msgstr ""
+
+#: forum/settings/repgain.py:44
+msgid ""
+"Reputation a user loses for having one of his accepted answers canceled."
+msgstr ""
+
+#: forum/settings/repgain.py:47
+msgid "Rep gain by accepting answer"
+msgstr ""
+
+#: forum/settings/repgain.py:48
+msgid ""
+"Reputation a user gains for accepting an answer to one of his questions."
+msgstr ""
+
+#: forum/settings/repgain.py:51
+msgid "Rep lost by canceling accepted"
+msgstr ""
+
+#: forum/settings/repgain.py:52
+msgid "Reputation a user loses by canceling an accepted answer."
+msgstr ""
+
+#: forum/settings/repgain.py:55
+msgid "Rep lost by post flagged"
+msgstr ""
+
+#: forum/settings/repgain.py:56
+msgid "Reputation a user loses by having one of his posts flagged."
+msgstr ""
+
+#: forum/settings/repgain.py:59
+msgid "Rep lost by post flagged and hidden"
+msgstr ""
+
+#: forum/settings/repgain.py:60
+msgid ""
+"Reputation a user loses by having the last revision of one of his posts "
+"flagged the enough number of times to hide the post."
+msgstr ""
+
+#: forum/settings/repgain.py:63
+msgid "Rep lost by post flagged and deleted"
+msgstr ""
+
+#: forum/settings/repgain.py:64
+msgid ""
+"Reputation a user loses by having the last revision of one of his posts "
+"flagged the enough number of times to delete the post."
+msgstr ""
+
+#: forum/settings/upload.py:5
+msgid "File upload settings"
+msgstr ""
+
+#: forum/settings/upload.py:5
+msgid "File uploads related settings."
+msgstr ""
+
+#: forum/settings/upload.py:8
+msgid "Uploaded files folder"
+msgstr ""
+
+#: forum/settings/upload.py:9
+msgid ""
+"The filesystem path where uploaded files will be stored. Please note that "
+"this folder must exist."
+msgstr ""
+
+#: forum/settings/upload.py:12
+msgid "Uploaded files alias"
+msgstr ""
+
+#: forum/settings/upload.py:13
+msgid ""
+"The url alias for uploaded files. Notice that if you change this setting, "
+"you'll need to restart your site."
+msgstr ""
+
+#: forum/settings/upload.py:16
+msgid "Max file size"
+msgstr ""
+
+#: forum/settings/upload.py:17
+msgid "The maximum allowed file size for uploads in mb."
+msgstr ""
+
+#: forum/settings/voting.py:4
+msgid "Voting rules"
+msgstr ""
+
+#: forum/settings/voting.py:4
+msgid "Configure the voting rules on your site."
+msgstr ""
+
+#: forum/settings/voting.py:7
+msgid "Maximum votes per day"
+msgstr ""
+
+#: forum/settings/voting.py:8
+msgid "The maximum number of votes an user can cast per day."
+msgstr ""
+
+#: forum/settings/voting.py:11
+msgid "Start warning about votes left"
+msgstr ""
+
+#: forum/settings/voting.py:12
+msgid "From how many votes left should an user start to be warned about it."
+msgstr ""
+
+#: forum/settings/voting.py:15
+msgid "Maximum flags per day"
+msgstr ""
+
+#: forum/settings/voting.py:16
+msgid "The maximum number of times an can flag a post per day."
+msgstr ""
+
+#: forum/settings/voting.py:19
+msgid "Flag count to hide post"
+msgstr ""
+
+#: forum/settings/voting.py:20
+msgid ""
+"How many times a post needs to be flagged to be hidden from the main page."
+msgstr ""
+
+#: forum/settings/voting.py:23
+msgid "Flag count to delete post"
+msgstr ""
+
+#: forum/settings/voting.py:24
+msgid "How many times a post needs to be flagged to be deleted."
+msgstr ""
+
+#: forum/settings/voting.py:27
+msgid "Days to cancel a vote"
+msgstr ""
+
+#: forum/settings/voting.py:28
+msgid "How many days an user can cancel a vote after he originaly casted it."
+msgstr ""
+
+#: forum/skins/default/templates/404.html:24
+msgid "Sorry, could not find the page you requested."
+msgstr ""
+
+#: forum/skins/default/templates/404.html:26
+msgid "This might have happened for the following reasons:"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:28
+msgid "this question or answer has been deleted;"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:29
+msgid "url has error - please check it;"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:30
+msgid ""
+"the page you tried to visit is protected or you don't have sufficient "
+"points, see"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:31
+msgid "if you believe this error 404 should not have occured, please"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:32
+msgid "report this problem"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:41
+#: forum/skins/default/templates/500.html:27
+msgid "back to previous page"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:42
+msgid "see all questions"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:43
+msgid "see all tags"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:22
+msgid "sorry, system error"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:24
+msgid "system error log is recorded, error will be fixed as soon as possible"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:25
+msgid "please report the error to the site administrators if you wish"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:28
+msgid "see latest questions"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:29
+msgid "see tags"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:12
+#: forum/skins/default/templates/book.html:105
+#: forum/skins/default/templates/question_summary_list_roll.html:14
+#: forum/skins/default/templates/question_list/item.html:10
+#: forum/views/commands.py:82
+msgid "votes"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:14
+msgid "this answer has been accepted to be correct"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:16
+#: forum/skins/default/templates/question_summary_list_roll.html:13
+#: forum/skins/default/templates/question_list/item.html:14
+msgid "answers"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:20
+#: forum/skins/default/templates/book.html:115
+#: forum/skins/default/templates/question_summary_list_roll.html:15
+#: forum/skins/default/templates/question_list/item.html:18
+msgid "views"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:34
+#: forum/skins/default/templates/question.html:234
+#: forum/skins/default/templates/question_summary_list_roll.html:52
+#: forum/skins/default/templates/tags.html:49
+#: forum/skins/default/templates/question_list/item.html:29
+msgid "see questions tagged"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:34
+#: forum/skins/default/templates/book.html:125
+#: forum/skins/default/templates/question.html:234
+#: forum/skins/default/templates/question_summary_list_roll.html:52
+#: forum/skins/default/templates/tags.html:49
+#: forum/skins/default/templates/question_list/item.html:29
+msgid "using tags"
+msgstr ""
+
+#: forum/skins/default/templates/about.html:5
+#: forum/skins/default/templates/about.html:9
+msgid "About"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:4
+msgid "Account functions"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:29
+#: forum/skins/default/templates/auth/auth_settings.html:31
+msgid "Change password"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:30
+msgid "Give your  account a new password."
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:32
+msgid "Change email "
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:33
+msgid "Add or update the email address associated with your account."
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:35
+msgid "Change OpenID"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:36
+msgid "Change openid associated to your account"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:39
+msgid "Delete account"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:40
+msgid "Erase your username and all your data from website"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:5
+#: forum/skins/default/templates/answer_edit.html:39
+msgid "Edit answer"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:18
+#: forum/skins/default/templates/answer_edit.html:21
+#: forum/skins/default/templates/ask.html:19
+#: forum/skins/default/templates/ask.html:22
+#: forum/skins/default/templates/question_edit.html:19
+#: forum/skins/default/templates/question_edit.html:22
+msgid "hide preview"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:21
+#: forum/skins/default/templates/ask.html:22
+#: forum/skins/default/templates/question_edit.html:22
+msgid "show preview"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:39
+#: forum/skins/default/templates/question_edit.html:63
+#: forum/skins/default/templates/question_retag.html:56
+#: forum/skins/default/templates/revisions_answer.html:36
+#: forum/skins/default/templates/revisions_question.html:35
+msgid "back"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:44
+#: forum/skins/default/templates/question_edit.html:68
+#: forum/skins/default/templates/revisions_answer.html:50
+#: forum/skins/default/templates/revisions_question.html:49
+msgid "revision"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:47
+#: forum/skins/default/templates/question_edit.html:72
+msgid "select revision"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:54
+#: forum/skins/default/templates/ask.html:93
+#: forum/skins/default/templates/question.html:184
+#: forum/skins/default/templates/question_edit.html:89
+msgid "Toggle the real time Markdown editor preview"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:54
+#: forum/skins/default/templates/ask.html:93
+#: forum/skins/default/templates/question.html:185
+#: forum/skins/default/templates/question_edit.html:89
+msgid "toggle preview"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:63
+#: forum/skins/default/templates/question_edit.html:115
+#: forum/skins/default/templates/question_retag.html:77
+msgid "Save edit"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:64
+#: forum/skins/default/templates/close.html:29
+#: forum/skins/default/templates/feedback.html:50
+#: forum/skins/default/templates/question_edit.html:116
+#: forum/skins/default/templates/question_retag.html:78
+#: forum/skins/default/templates/reopen.html:30
+#: forum/skins/default/templates/users/edit.html:87
+msgid "Cancel"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:4
+msgid "answer tips"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:7
+msgid "please make your answer relevant to this community"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:10
+msgid "try to give an answer, rather than engage into a discussion"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:13
+msgid "please try to provide details"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:16
+#: forum/skins/default/templates/question_edit_tips.html:18
+msgid "be clear and concise"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:20
+#: forum/skins/default/templates/question_edit_tips.html:22
+msgid "see frequently asked questions"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:26
+#: forum/skins/default/templates/question_edit_tips.html:28
+msgid "Markdown tips"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:29
+#: forum/skins/default/templates/question_edit_tips.html:31
+msgid "*italic* or __italic__"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:32
+#: forum/skins/default/templates/question_edit_tips.html:34
+msgid "**bold** or __bold__"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:35
+#: forum/skins/default/templates/question_edit_tips.html:37
+msgid "link"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:35
+#: forum/skins/default/templates/answer_edit_tips.html:39
+#: forum/skins/default/templates/question_edit_tips.html:37
+#: forum/skins/default/templates/question_edit_tips.html:42
+msgid "text"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:39
+#: forum/skins/default/templates/question_edit_tips.html:42
+msgid "image"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:43
+#: forum/skins/default/templates/question_edit_tips.html:46
+msgid "numbered list:"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:48
+#: forum/skins/default/templates/question_edit_tips.html:51
+msgid "basic HTML tags are also supported"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:52
+#: forum/skins/default/templates/question_edit_tips.html:55
+msgid "learn more about Markdown"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:5
+#: forum/skins/default/templates/ask.html:57
+msgid "Ask a question"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:64
+msgid "login to post question info"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:70
+#, python-format
+msgid ""
+"must have valid %(email)s to post, \n"
+"                            see %(email_validation_faq_url)s\n"
+"                            "
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:108
+msgid "(required)"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:115
+msgid "Login/signup to post your question"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:117
+msgid "Ask your question"
+msgstr ""
+
+#: forum/skins/default/templates/badge.html:6
+#: forum/skins/default/templates/badge.html:17
+msgid "Badge"
+msgstr ""
+
+#: forum/skins/default/templates/badge.html:26
+msgid "The users have been awarded with badges:"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:6
+msgid "Badges summary"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:17
+msgid "Badges"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:21
+msgid "Community gives you awards for your questions, answers and votes."
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:22
+#, python-format
+msgid ""
+"Below is the list of available badges and number \n"
+"    of times each type of badge has been awarded. Give us feedback at %"
+"(feedback_faq_url)s.\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:50
+msgid "Community badges"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:56
+msgid "gold badge description"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:64
+msgid "silver badge description"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:67
+msgid "bronze badge: often given as a special honor"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:71
+msgid "bronze badge description"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:7
+msgid "reading channel"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:26
+msgid "[author]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:30
+msgid "[publisher]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:34
+msgid "[publication date]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:38
+msgid "[price]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:39
+msgid "currency unit"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:42
+msgid "[pages]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:43
+msgid "pages abbreviation"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:46
+msgid "[tags]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:56
+msgid "author blog"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:62
+msgid "book directory"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:66
+msgid "buy online"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:79
+msgid "reader questions"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:82
+msgid "ask the author"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:88
+#: forum/skins/default/templates/book.html:93
+msgid "this question was selected as favorite"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:88
+#: forum/skins/default/templates/book.html:93
+msgid "number of times"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:108
+msgid "the answer has been accepted to be correct"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:147
+msgid "subscribe to book RSS feed"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:147
+msgid "subscribe to the questions feed"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:6
+#: forum/skins/default/templates/close.html:16
+msgid "Close question"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:19
+msgid "Close the question"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:25
+msgid "Reasons"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:28
+msgid "OK to close"
+msgstr ""
+
+#: forum/skins/default/templates/email_base.html:31
+msgid "home"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:11
+msgid "Frequently Asked Questions "
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:16
+msgid "What kinds of questions can I ask here?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:17
+msgid ""
+"Most importantly - questions should be <strong>relevant</strong> to this "
+"community."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:18
+msgid ""
+"Before asking the question - please make sure to use search to see whether "
+"your question has alredy been answered."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:21
+msgid "What questions should I avoid asking?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:22
+msgid ""
+"Please avoid asking questions that are not relevant to this community, too "
+"subjective and argumentative."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:27
+msgid "What should I avoid in my answers?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:28
+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 ""
+
+#: forum/skins/default/templates/faq.html:32
+msgid "Who moderates this community?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:33
+msgid "The short answer is: <strong>you</strong>."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:34
+msgid "This website is moderated by the users."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:35
+msgid ""
+"The reputation system allows users earn the authorization to perform a "
+"variety of moderation tasks."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:40
+msgid "How does reputation system work?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:41
+msgid "Rep system summary"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:42
+msgid ""
+"For example, if you ask an interesting question or give a helpful answer, "
+"your input will be upvoted. On the other hand if the answer is misleading - "
+"it will be downvoted. Each vote in favor will generate <strong>10</strong> "
+"points, each vote against will subtract <strong>2</strong> points. There is "
+"a limit of <strong>200</strong> points that can be accumulated per question "
+"or answer. The table below explains reputation point requirements for each "
+"type of moderation task."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:53
+#: forum/skins/default/templates/users/votes.html:15
+#: forum/views/commands.py:77
+msgid "upvote"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:57
+msgid "use tags"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:62
+msgid "add comments"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:66
+#: forum/skins/default/templates/users/votes.html:17
+#: forum/views/commands.py:77
+msgid "downvote"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:69
+msgid "open and close own questions"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:73
+msgid "retag questions"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:78
+msgid "edit community wiki questions"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:83
+msgid "edit any answer"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:87
+msgid "open any closed question"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:91
+msgid "delete any comment"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:95
+msgid "delete any questions and answers and perform other moderation tasks"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:103
+msgid "how to validate email title"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:105
+#, python-format
+msgid ""
+"how to validate email info with %(send_email_key_url)s %(gravatar_faq_url)s"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:110
+msgid "what is gravatar"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:111
+msgid "gravatar faq info"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:114
+msgid "To register, do I need to create new password?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:115
+msgid ""
+"No, you don't have to. You can login through any service that supports "
+"OpenID, e.g. Google, Yahoo, AOL, etc."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:116
+msgid "Login now!"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:121
+msgid "Why other people can edit my questions/answers?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:122
+msgid "Goal of this site is..."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:122
+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 ""
+
+#: forum/skins/default/templates/faq.html:123
+msgid "If this approach is not for you, we respect your choice."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:127
+msgid "Still have questions?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:128
+#, python-format
+msgid ""
+"Please ask your question at %(ask_question_url)s, help make our community "
+"better!"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:130
+#: forum/skins/default/templates/header.html:30
+#: forum/skins/default/templates/header.html:55 forum/views/readers.py:76
+msgid "questions"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:130
+msgid "."
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:6
+msgid "Feedback"
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:11
+msgid "Give us your feedback!"
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:17
+#, python-format
+msgid ""
+"\n"
+"            <span class='big strong'>Dear %(user_name)s</span>, we look "
+"forward to hearing your feedback. \n"
+"            Please type and send us your message below.\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:24
+msgid ""
+"\n"
+"            <span class='big strong'>Dear visitor</span>, we look forward to "
+"hearing your feedback.\n"
+"            Please type and send us your message below.\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:41
+msgid "(this field is required)"
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:49
+msgid "Send Feedback"
+msgstr ""
+
+#: forum/skins/default/templates/footer.html:7
+#: forum/skins/default/templates/header.html:16
+#: forum/skins/default/templates/index.html:12
+msgid "about"
+msgstr ""
+
+#: forum/skins/default/templates/footer.html:8
+#: forum/skins/default/templates/header.html:17
+#: forum/skins/default/templates/index.html:13
+#: forum/skins/default/templates/question_edit_tips.html:22
+msgid "faq"
+msgstr ""
+
+#: forum/skins/default/templates/footer.html:9
+msgid "privacy policy"
+msgstr ""
+
+#: forum/skins/default/templates/footer.html:18
+msgid "give feedback"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:9
+msgid "administration"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:12
+msgid "logout"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:14
+msgid "login"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:24
+msgid "back to home page"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:32
+#: forum/skins/default/templates/header.html:57
+msgid "users"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:33
+#: forum/skins/default/templates/users/signature.html:9
+#: forum/skins/default/templates/users/signature.html:15
+#: forum/skins/default/templates/users/signature.html:21
+#: forum/templatetags/extra_tags.py:167 forum/templatetags/extra_tags.py:196
+msgid "badges"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:34
+msgid "unanswered questions"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:36
+msgid "ask a question"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:51
+msgid "search"
+msgstr ""
+
+#: forum/skins/default/templates/index.html:9
+msgid "welcome to "
+msgstr ""
+
+#: forum/skins/default/templates/logout.html:6
+#: forum/skins/default/templates/logout.html:16
+msgid "Logout"
+msgstr ""
+
+#: forum/skins/default/templates/logout.html:19
+msgid ""
+"As a registered user you can login with your OpenID, log out of the site or "
+"permanently remove your account."
+msgstr ""
+
+#: forum/skins/default/templates/logout.html:20
+msgid "Logout now"
+msgstr ""
+
+#: forum/skins/default/templates/notarobot.html:3
+msgid "Please prove that you are a Human Being"
+msgstr ""
+
+#: forum/skins/default/templates/notarobot.html:10
+msgid "I am a Human Being"
+msgstr ""
+
+#: forum/skins/default/templates/pagesize.html:6
+msgid "posts per page"
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:6
+#: forum/skins/default/templates/paginator.html:7
+msgid "previous"
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:19
+msgid "current page"
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:22
+#: forum/skins/default/templates/paginator.html:29
+msgid "page number "
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:22
+#: forum/skins/default/templates/paginator.html:29
+msgid "number - make blank in english"
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:33
+msgid "next page"
+msgstr ""
+
+#: forum/skins/default/templates/post_contributor_info.html:9
+#, python-format
+msgid ""
+"\n"
+"                one revision\n"
+"            "
+msgid_plural ""
+"\n"
+"                %(rev_count)s revisions\n"
+"            "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/post_contributor_info.html:24
+msgid "posted"
+msgstr ""
+
+#: forum/skins/default/templates/post_contributor_info.html:45
+msgid "updated"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:6
+#: forum/skins/default/templates/privacy.html:11
+msgid "Privacy policy"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:15
+msgid "general message about privacy"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:18
+msgid "Site Visitors"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:20
+msgid "what technical information is collected about visitors"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:23
+msgid "Personal Information"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:25
+msgid "details on personal information policies"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:28
+msgid "Other Services"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:30
+msgid "details on sharing data with third parties"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:35
+msgid "cookie policy details"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:37
+msgid "Policy Changes"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:38
+msgid "how privacy policies can be changed"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:70
+#: forum/skins/default/templates/sidebar/recent_tags.html:9
+#, python-format
+msgid "see questions tagged '%(tagname)s'"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:87
+#, python-format
+msgid ""
+"The question has been closed for the following reason \"%(close_reason)s\" by"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:89
+#, python-format
+msgid "close date %(closed_at)s"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:97
+#, python-format
+msgid ""
+"\n"
+"                    One Answer:\n"
+"                    "
+msgid_plural ""
+"\n"
+"                    %(counter)s Answers:\n"
+"                    "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/question.html:105
+msgid "oldest answers will be shown first"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:105
+msgid "oldest answers"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:107
+msgid "newest answers will be shown first"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:107
+msgid "newest answers"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:109
+msgid "most voted answers will be shown first"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:109
+msgid "popular answers"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:157
+msgid "Your answer"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:159
+msgid "Be the first one to answer this question!"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:165
+msgid "you can answer anonymously and then login"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:169
+msgid "answer your own question only to give an answer"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:171
+msgid "please only give an answer, no discussions"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:207
+msgid "Login/Signup to Post Your Answer"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:210
+msgid "Answer Your Own Question"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:212
+msgid "Answer the question"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:229
+msgid "Question tags"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:239
+msgid "question asked"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:242
+msgid "question was seen"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:242
+msgid "times"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:245
+msgid "last updated"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:250
+msgid "Related questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_edit.html:5
+#: forum/skins/default/templates/question_edit.html:63
+msgid "Edit question"
+msgstr ""
+
+#: forum/skins/default/templates/question_edit_tips.html:4
+msgid "question tips"
+msgstr ""
+
+#: forum/skins/default/templates/question_edit_tips.html:9
+#, python-format
+msgid ""
+"\n"
+"                ask a question relevant to the %(app_title)s community \n"
+"                "
+msgstr ""
+
+#: forum/skins/default/templates/question_edit_tips.html:15
+msgid "please try provide enough details"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:5
+#: forum/skins/default/templates/question_retag.html:56
+msgid "Change tags"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:44
+msgid "up to 5 tags, less than 20 characters each"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:86
+msgid "Why use and modify tags?"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:89
+msgid "tags help us keep Questions organized"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:97
+msgid "tag editors receive special awards from the community"
+msgstr ""
+
+#: forum/skins/default/templates/questions.html:7
+msgid "Questions"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:6
+#: forum/skins/default/templates/reopen.html:16
+msgid "Reopen question"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:19
+msgid "Open the previously closed question"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:22
+msgid "The question was closed for the following reason "
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:22
+msgid "reason - leave blank in english"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:22
+msgid "on "
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:22
+msgid "date closed"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:29
+msgid "Reopen this question"
+msgstr ""
+
+#: forum/skins/default/templates/revisions_answer.html:7
+#: forum/skins/default/templates/revisions_answer.html:36
+#: forum/skins/default/templates/revisions_question.html:7
+#: forum/skins/default/templates/revisions_question.html:35
+msgid "Revision history"
+msgstr ""
+
+#: forum/skins/default/templates/revisions_answer.html:48
+#: forum/skins/default/templates/revisions_question.html:47
+msgid "click to hide/show revision"
+msgstr ""
+
+#: forum/skins/default/templates/revisions_answer.html:56
+#: forum/templatetags/node_tags.py:62
+msgid "edit"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:3
+msgid "Subscription"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:8
+msgid "You were automatically subscribed to this question."
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:10
+msgid "You are subscribed to this question."
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:13
+msgid "You are not subscribed to this question."
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:18
+#: forum/views/commands.py:323
+msgid "unsubscribe me"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:20
+#: forum/views/commands.py:323
+msgid "subscribe me"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:24
+#, python-format
+msgid ""
+"\n"
+"            (you can adjust your notification settings on your <a href=\"%"
+"(profile_url)s?sort=email_subscriptions\">profile</a>)\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:29
+msgid "Once you sign in you will be able to subscribe for any updates here"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:4
+#: forum/skins/default/templates/question_list/tag_selector.html:6
+msgid "Interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:10
+#: forum/skins/default/templates/tag_selector.html:27
+#: forum/skins/default/templates/question_list/related_tags.html:9
+#: forum/skins/default/templates/question_list/tag_selector.html:12
+#: forum/skins/default/templates/question_list/tag_selector.html:29
+#, python-format
+msgid "see questions tagged '%(tag_name)s'"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:14
+#: forum/skins/default/templates/question_list/tag_selector.html:16
+#, python-format
+msgid "remove '%(tag_name)s' from the list of interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:20
+#: forum/skins/default/templates/tag_selector.html:37
+#: forum/skins/default/templates/question_list/tag_selector.html:22
+#: forum/skins/default/templates/question_list/tag_selector.html:39
+msgid "Add"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:21
+#: forum/skins/default/templates/question_list/tag_selector.html:23
+msgid "Ignored tags"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:31
+#: forum/skins/default/templates/question_list/tag_selector.html:33
+#, python-format
+msgid "remove '%(tag_name)s' from the list of ignored tags"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:40
+#: forum/skins/default/templates/question_list/tag_selector.html:42
+msgid "keep ignored questions hidden"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:6
+#: forum/skins/default/templates/tags.html:30
+msgid "Tag list"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:32
+msgid "sorted alphabetically"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:32
+msgid "by name"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:33
+msgid "sorted by frequency of tag use"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:33
+msgid "by popularity"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:39
+msgid "All tags matching query"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:39
+msgid "all tags - make this empty in english"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:42
+msgid "Nothing found"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:5
+#: forum/skins/default/templates/auth/auth_settings.html:7
+msgid "Authentication settings"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:9
+msgid ""
+"These are the external authentication providers currently associated with "
+"your account."
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:12
+msgid "remove"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:17
+msgid ""
+"You currently have no external authentication provider associated with your "
+"account."
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:19
+msgid "Add new provider"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:21
+msgid "This is where you can change your password. Make sure you remember it!"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:24
+msgid ""
+"You can set up a password for your account, so you can login using standard "
+"username and password!"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:31
+msgid "Create password"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:5
+msgid "Connect your OpenID with this site"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:8
+msgid "Connect your OpenID with your account on this site"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:12
+msgid "You are here for the first time with "
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:13
+msgid ""
+"Please create your screen name and save your email address. Saved email "
+"address will let you subscribe for the updates on the most interesting "
+"questions and will be used to create and retrieve your unique avatar image. "
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:15
+msgid "This account already exists, please use another."
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:30
+msgid "Sorry, looks like we have some errors:"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:47
+msgid "Screen name label"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:54
+msgid "Email address label"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:60
+#: forum/skins/default/templates/auth/signup.html:18
+msgid "receive updates motivational blurb"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:64
+#: forum/skins/default/templates/auth/signup.html:22
+msgid "please select one of the options above"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:67
+msgid "Tag filter tool will be your right panel, once you log in."
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:68
+msgid "create account"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:77
+msgid "Existing account"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:78
+msgid "user name"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:79
+msgid "password"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:86
+msgid "Register"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:87
+msgid "Forgot your password?"
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:6
+#: forum/skins/default/templates/auth/temp_login_email.html:6
+msgid "Greetings from the Q&A forum"
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:8
+msgid "To make use of the Forum, please follow the link below:"
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:12
+msgid "Following the link above will help us verify your email address."
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:14
+#: forum/skins/default/templates/auth/temp_login_email.html:14
+msgid ""
+"If you beleive that this message was sent in mistake -\n"
+"    no further action is needed. Just ingore this email, we apologize\n"
+"    for any inconvenience"
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:18
+#: forum/skins/default/templates/auth/temp_login_email.html:18
+#: forum/skins/default/templates/notifications/answeraccepted.html:15
+#: forum/skins/default/templates/notifications/newanswer.html:25
+#: forum/skins/default/templates/notifications/newcomment.html:32
+#: forum/skins/default/templates/notifications/newmember.html:15
+#: forum/skins/default/templates/notifications/newquestion.html:25
+msgid ""
+"Sincerely,<br />\n"
+"    Forum Administrator"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:6
+msgid "Login"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:24
+msgid "User login"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:36
+#: forum/skins/default/templates/auth/signin.html:86
+#: forum/skins/default/templates/auth/signin.html:92
+msgid "Or..."
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:39
+msgid "Click to sign in through any of these services."
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:44
+msgid "Validate my email after I login."
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:94
+msgid "Click"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:94
+msgid "if you're having troubles signing in."
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:98
+msgid "Enter your "
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:154
+msgid "Why use OpenID?"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:157
+msgid "with openid it is easier"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:160
+msgid "reuse openid"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:163
+msgid "openid is widely adopted"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:166
+msgid "openid is supported open standard"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:171
+msgid "Find out more"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:172
+msgid "Get OpenID"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:4
+msgid "Signup"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:8
+msgid "Create login name and password"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:10
+msgid "Traditional signup info"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:31
+msgid "Create Account"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:32
+msgid "or"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:33
+msgid "return to login page"
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_email.html:8
+msgid "You're seeing this because someone requested a temporary login link"
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_email.html:12
+msgid "Following the link above will give you access to your account."
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:5
+msgid "Request temporary login key"
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:7
+msgid "Account: request temporary login key"
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:8
+msgid ""
+"\n"
+"    If you're experiencing problems accessing your account, or if you forgot "
+"your password,\n"
+"    here you can request a temporary login key. Fill out your account email "
+"and we'll send you a temporary access link that\n"
+"    will enable you to access your account. This token is valid only once "
+"and for a limited period of time.\n"
+" "
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:25
+msgid "Send link"
+msgstr ""
+
+#: forum/skins/default/templates/node/accept_button.html:5
+#, python-format
+msgid "%(who)s has selected this answer as the correct answer"
+msgstr ""
+
+#: forum/skins/default/templates/node/accept_button.html:5
+msgid "mark this answer as the accepted answer"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:22
+msgid "I like this comment (click again to cancel)"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:26
+msgid "Edit comment"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:30
+msgid "Delete comment"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:42
+#, python-format
+msgid "showing %(showing)s of %(total)s"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:44
+msgid "show all"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:47
+msgid "add new comment"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:55
+msgid " add comment"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:58
+#, python-format
+msgid ""
+"\n"
+"                have <span class=\"comments-char-left-count\">%(max_length)"
+"s</span> characters left\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:71
+msgid "just now"
+msgstr ""
+
+#: forum/skins/default/templates/node/favorite_mark.html:3
+msgid "mark/unmark this question as favorite (click again to cancel)"
+msgstr ""
+
+#: forum/skins/default/templates/node/vote_buttons.html:3
+msgid "I like this post (click again to cancel)"
+msgstr ""
+
+#: forum/skins/default/templates/node/vote_buttons.html:7
+msgid "current number of votes"
+msgstr ""
+
+#: forum/skins/default/templates/node/vote_buttons.html:10
+msgid "I dont like this post (click again to cancel)"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/answeraccepted.html:6
+#: forum/skins/default/templates/notifications/digest.html:7
+#: forum/skins/default/templates/notifications/newanswer.html:6
+#: forum/skins/default/templates/notifications/newcomment.html:6
+#: forum/skins/default/templates/notifications/newmember.html:6
+#: forum/skins/default/templates/notifications/newquestion.html:6
+msgid "Hello"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/answeraccepted.html:9
+#, python-format
+msgid ""
+"\n"
+"        Just to let you know that %(accepter)s has just accepted %"
+"(answer_author)s's answer on his question\n"
+"        <a href=\"%(app_url)s%(question_url)s\">%(question_title)s</a>:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:9
+#, python-format
+msgid ""
+"\n"
+"    This is the %(digest_type)s activity digest for %(app_title)s\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:15
+#, python-format
+msgid ""
+"\n"
+"            %(nusers_count)s new user%(nusers_count_pluralize)s joined the %"
+"(app_title)s community:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:28
+#, python-format
+msgid ""
+"\n"
+"            %(question_count)s of your subscriptions have updates:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:35
+msgid "On question "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:37
+#, python-format
+msgid ""
+"\n"
+"                    %(answer_count)s new answer%(answer_count_pluralize)s\n"
+"                "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:42
+#, python-format
+msgid ""
+"\n"
+"                    %(comment_count)s new comment%(comment_count_pluralize)"
+"s\n"
+"                "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:46
+msgid "on your own post(s)"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:50
+msgid "an answer was accepted"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:59
+#, python-format
+msgid ""
+"\n"
+"            %(question_count)s new question%(question_count_pluralize)s\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:63
+msgid "matching your interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:65
+msgid "posted :"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:71
+#, python-format
+msgid ""
+"\n"
+"                    Posted by %(author_name)s in %(question_time)s\n"
+"                "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:7
+#, python-format
+msgid ""
+"\n"
+"    Hello, this is a %(site_title)s forum feedback message\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:13
+msgid "Sender"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:15
+#: forum/skins/default/templates/notifications/feedback.html:18
+#: forum/skins/default/templates/users/info.html:93
+msgid "email"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:17
+msgid "anonymous"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:25
+msgid "Message body:"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newanswer.html:9
+#, python-format
+msgid ""
+"\n"
+"        %(author_name)s has just posted a new answer on %(app_title)s to the "
+"question\n"
+"        <a href=\"%(app_url)s%(question_url)s\">%(question_title)s\"</a>:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newanswer.html:20
+#: forum/skins/default/templates/notifications/newcomment.html:28
+#: forum/skins/default/templates/notifications/newquestion.html:20
+msgid ""
+"\n"
+"        Don't forget to come over and cast your vote.\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newcomment.html:9
+#, python-format
+msgid ""
+"\n"
+"            %(author_name)s has just posted a comment on\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newcomment.html:14
+#, python-format
+msgid ""
+"\n"
+"                the answer posted by <a href=\"%(app_url)s%(poster_url)s\">%"
+"(poster_name)s</a> to\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newcomment.html:19
+#, python-format
+msgid ""
+"\n"
+"             the question  <a href=\"%(app_url)s%(question_url)s\">%"
+"(question_title)s</a>\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newmember.html:9
+#, python-format
+msgid ""
+"\n"
+"        %(newmember_name)s has just joined %(app_title)s. You can visit %"
+"(newmember_name)s's profile using the following link: <br />\n"
+"        <a href=\"%(app_url)s%(newmember_url)s\">%(newmember_name)s profile</"
+"a>\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newquestion.html:9
+#, python-format
+msgid ""
+"\n"
+"        %(author_name)s has just posted a new question on %(app_title)s, "
+"with title\n"
+"        <a href=\"%(app_url)s%(question_url)s\">%(question_title)s</a> and "
+"tagged <em>%(question_tags)s</em>:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/base.html:13
+msgid "OSQA administration area"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/base.html:26
+msgid "Administration menu"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:7
+msgid "Dashboard"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:10
+msgid "Welcome to the OSQA administration area."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:17
+msgid "Site statistics"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:21
+#: forum/skins/default/templates/osqaadmin/index.html:26
+msgid "in the last 24 hours"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:31
+msgid "user"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:31
+msgid "joined in the last 24 hours"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:37
+msgid "Site status"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:42
+msgid ""
+"Your site is running in bootstrap mode, click the button bellow to revert to "
+"defaults."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:45
+msgid ""
+"Your site is running in standard mode, click the button bellow to run in "
+"bootstrap mode."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:47
+msgid ""
+"Your site is running with some customized settings, click the buttons bellow "
+"to run with defaults or in bootstrap mode"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:51
+msgid "Are you sure you want to revert to the defaults?"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:51
+msgid "revert to defaults"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:54
+msgid "Are you sure you want to run bootstrap mode?"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:54
+msgid "go bootstrap"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:59
+msgid "Recalculate scores and reputation"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:60
+msgid "This is a heavy operation, are you sure?"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:60
+msgid "Recalculate"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:65
+msgid "Recent activity"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/item.html:12
+msgid "this question has an accepted answer"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/related_tags.html:6
+msgid "Related tags"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:4
+msgid "most recently updated questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:4
+msgid "active"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:5
+msgid "most recently asked questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:5
+msgid "newest"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:6
+msgid "hottest questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:6
+msgid "hottest"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:7
+msgid "most voted questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:7
+msgid "most voted"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:5
+msgid "Found by tags"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:9
+msgid "Search results"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:11
+msgid "Found by title"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:15
+msgid "Unanswered questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:17
+#: forum/skins/default/templates/users/subscriptions.html:74
+msgid "All questions"
+msgstr ""
+
+#: forum/skins/default/templates/sidebar/recent_awards.html:4
+msgid "Recent awards"
+msgstr ""
+
+#: forum/skins/default/templates/sidebar/recent_awards.html:15
+msgid "all awards"
+msgstr ""
+
+#: forum/skins/default/templates/sidebar/recent_tags.html:4
+msgid "Recent tags"
+msgstr ""
+
+#: forum/skins/default/templates/sidebar/recent_tags.html:12
+msgid "popular tags"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:6
+msgid "Edit user profile"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:19
+msgid "edit profile"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:31
+msgid "image associated with your email address"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:31
+#, python-format
+msgid "avatar, see %(gravatar_faq_url)s"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:36
+#: forum/skins/default/templates/users/info.html:52
+msgid "Registered user"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:43
+msgid "Screen Name"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:86
+#: forum/skins/default/templates/users/subscriptions.html:116
+msgid "Update"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:22
+#: forum/skins/default/templates/users/signature.html:6
+#: forum/skins/default/templates/users/users.html:26
+msgid "reputation"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:32
+msgid "Moderate this user"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:44
+msgid "update profile"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:56
+msgid "real name"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:61
+msgid "member for"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:66
+msgid "last seen"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:72
+msgid "user website"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:78
+msgid "location"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:86
+msgid "age"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:87
+msgid "age unit"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:100
+msgid "todays unused votes"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:101
+msgid "votes left"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:13
+#, python-format
+msgid ""
+"\n"
+"                <span class=\"count\">1</span> Question\n"
+"                "
+msgid_plural ""
+"\n"
+"                <span class=\"count\">%(counter)s</span> Questions\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:29
+#, python-format
+msgid ""
+"\n"
+"                <span class=\"count\">1</span> Answer\n"
+"                "
+msgid_plural ""
+"\n"
+"                <span class=\"count\">%(counter)s</span> Answers\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:42
+#, python-format
+msgid "the answer has been voted for %(vote_count)s times"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:42
+msgid "this answer has been selected as correct"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:58
+#, python-format
+msgid ""
+"\n"
+"                    <span class=\"count\">1</span> Vote\n"
+"                "
+msgid_plural ""
+"\n"
+"                    <span class=\"count\">%(cnt)s</span> Votes\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:69
+msgid "thumb up"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:70
+msgid "user has voted up this many times"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:74
+msgid "thumb down"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:75
+msgid "user voted down this many times"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:84
+#, python-format
+msgid ""
+"\n"
+"                    <span class=\"count\">1</span> Tag\n"
+"                "
+msgid_plural ""
+"\n"
+"                    <span class=\"count\">%(counter)s</span> Tags\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:97
+#, python-format
+msgid ""
+"see other questions with %(view_user)s's contributions tagged '%(tag_name)s' "
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:112
+#, python-format
+msgid ""
+"\n"
+"            <span class=\"count\">1</span> Badge\n"
+"            "
+msgid_plural ""
+"\n"
+"            <span class=\"count\">%(counter)s</span> Badges\n"
+"            "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/subscriptions.html:8
+msgid "Notifications and subscription settings"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:10
+msgid ""
+"\n"
+"        Here you can decide which types of notifications you wish to "
+"receive, and it's frequency.<br />\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:14
+msgid ""
+"\n"
+"        Currently you have notifications enabled. You can always stop all "
+"notifications without loosing your settings and restart them afterwards.<br /"
+">\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:18
+msgid ""
+"\n"
+"        Currently you have notifications disabled. You can enable them "
+"clicking on the <strong>Start notifications</strong> button bellow.<br />\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:28
+msgid "Notify me when:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:32
+msgid "A new member joins"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:36
+msgid "A new question is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:40
+msgid "A new question matching my interesting tags is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:44
+msgid "There's an update on one of my subscriptions"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:52
+msgid "Auto subscribe me to:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:57
+msgid "Questions I ask"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:60
+msgid "Questions I answer"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:63
+msgid "Questions I comment"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:68
+msgid "Questions I view"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:71
+msgid "All questions matching my interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:82
+msgid "On my subscriptions, notify me when:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:87
+msgid "An answer is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:90
+msgid "A comment on one of my posts is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:95
+msgid "A comment is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:98
+msgid "An answer is accepted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:106
+msgid "More:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:111
+msgid ""
+"Notify me when someone replys to one of my comments on any post using the "
+"<pre>@username</pre> notation"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:118
+msgid "Stop notifications"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:120
+msgid "Start notifications"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:7
+msgid "User profile"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:7
+msgid "overview"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:9
+msgid "recent activity"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:11
+msgid "graph of user reputation"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:12
+msgid "reputation history"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:15 forum/views/users.py:196
+msgid "user vote record"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:15
+msgid "casted votes"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:18
+msgid "questions that user selected as his/her favorite"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:19
+msgid "favorites"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:22
+msgid "email subscription settings"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:23
+msgid "subscriptions"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:6
+#: forum/skins/default/templates/users/users.html:24
+msgid "Users"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:27
+msgid "recent"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:28
+msgid "oldest"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:29
+msgid "by username"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:35
+#, python-format
+msgid "users matching query %(suser)s:"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:39
+msgid "Nothing found."
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:168 forum/templatetags/extra_tags.py:195
+msgid "reputation points"
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:248
+msgid "2 days ago"
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:250
+msgid "yesterday"
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:252
+#, python-format
+msgid "%(hr)d hour ago"
+msgid_plural "%(hr)d hours ago"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/templatetags/extra_tags.py:254
+#, python-format
+msgid "%(min)d min ago"
+msgid_plural "%(min)d mins ago"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/templatetags/node_tags.py:58
+msgid "permanent link"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:58
+msgid "answer permanent link"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:64
+msgid "retag"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:68
+msgid "reopen"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:70
+msgid "close"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:73 forum/views/commands.py:124
+#: forum/views/commands.py:136
+msgid "flag"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:79
+msgid ""
+"report as offensive (i.e containing spam, advertising, malicious text, etc.)"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:82
+msgid "delete"
+msgstr ""
+
+#: forum/templatetags/question_list_tags.py:57
+msgid "<strong>Newest</strong> questions are shown first. "
+msgstr ""
+
+#: forum/templatetags/question_list_tags.py:58
+msgid "Questions are sorted by the <strong>time of last update</strong>."
+msgstr ""
+
+#: forum/templatetags/question_list_tags.py:59
+msgid "Questions sorted by <strong>number of responses</strong>."
+msgstr ""
+
+#: forum/templatetags/question_list_tags.py:60
+msgid "Questions are sorted by the <strong>number of votes</strong>."
+msgstr ""
+
+#: forum/templatetags/user_tags.py:58 forum/views/readers.py:293
+#, python-format
+msgid "Revision n. %(rev_number)d"
+msgstr ""
+
+#: forum/utils/forms.py:32
+msgid "this field is required"
+msgstr ""
+
+#: forum/utils/forms.py:47
+msgid "choose a username"
+msgstr ""
+
+#: forum/utils/forms.py:52
+msgid "user name is required"
+msgstr ""
+
+#: forum/utils/forms.py:53
+msgid "sorry, this name is taken, please choose another"
+msgstr ""
+
+#: forum/utils/forms.py:54
+msgid "sorry, this name is not allowed, please choose another"
+msgstr ""
+
+#: forum/utils/forms.py:55
+msgid "sorry, there is no user with this name"
+msgstr ""
+
+#: forum/utils/forms.py:56
+msgid "sorry, we have a serious error - user name is taken by several users"
+msgstr ""
+
+#: forum/utils/forms.py:57
+msgid "user name can only consist of letters, empty space and underscore"
+msgstr ""
+
+#: forum/utils/forms.py:105
+msgid "your email address"
+msgstr ""
+
+#: forum/utils/forms.py:106
+msgid "email address is required"
+msgstr ""
+
+#: forum/utils/forms.py:108
+msgid "this email is already used by someone else, please choose another"
+msgstr ""
+
+#: forum/utils/forms.py:133
+msgid "choose password"
+msgstr ""
+
+#: forum/utils/forms.py:134
+msgid "password is required"
+msgstr ""
+
+#: forum/utils/forms.py:137
+msgid "retype password"
+msgstr ""
+
+#: forum/utils/forms.py:138
+msgid "please, retype your password"
+msgstr ""
+
+#: forum/utils/forms.py:139
+msgid "sorry, entered passwords did not match, please try again"
+msgstr ""
+
+#: forum/views/admin.py:47
+#, python-format
+msgid "'%s' settings saved succesfully"
+msgstr ""
+
+#: forum/views/admin.py:141
+msgid "Bootstrap mode enabled"
+msgstr ""
+
+#: forum/views/admin.py:155
+msgid "All values reverted to defaults"
+msgstr ""
+
+#: forum/views/admin.py:171
+msgid "All values recalculated"
+msgstr ""
+
+#: forum/views/auth.py:103 forum/views/auth.py:112
+msgid ""
+"Sorry, these login credentials belong to anoother user. Plese terminate your "
+"current session and try again."
+msgstr ""
+
+#: forum/views/auth.py:105
+msgid "You are already logged in with that user."
+msgstr ""
+
+#: forum/views/auth.py:110
+msgid "These login credentials are already associated with your account."
+msgstr ""
+
+#: forum/views/auth.py:116
+msgid "The new credentials are now associated with your account"
+msgstr ""
+
+#: forum/views/auth.py:157
+msgid ""
+"Oops, something went wrong in the middle of this process. Please try again."
+msgstr ""
+
+#: forum/views/auth.py:219
+msgid "Temporary login link"
+msgstr ""
+
+#: forum/views/auth.py:224
+msgid "An email has been sent with your temporary login key"
+msgstr ""
+
+#: forum/views/auth.py:239
+msgid ""
+"You are logged in with a temporary access key, please take the time to fix "
+"your issue with authentication."
+msgstr ""
+
+#: forum/views/auth.py:245
+msgid "Email Validation"
+msgstr ""
+
+#: forum/views/auth.py:256
+msgid "Thank you, your email is now validated."
+msgstr ""
+
+#: forum/views/auth.py:280
+msgid "Your password was changed"
+msgstr ""
+
+#: forum/views/auth.py:282
+msgid "New password set"
+msgstr ""
+
+#: forum/views/auth.py:315
+#, python-format
+msgid "You removed the association with %s"
+msgstr ""
+
+#: forum/views/auth.py:353
+#, python-format
+msgid "Welcome back %s, you are now logged in"
+msgstr ""
+
+#: forum/views/commands.py:20
+#, python-format
+msgid ""
+"\n"
+"            Sorry, but you don't have enough reputation points to %(action)s."
+"<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:29
+#, python-format
+msgid ""
+"\n"
+"            Sorry but you cannot %(action)s your own post.<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:38
+#, python-format
+msgid ""
+"\n"
+"            Sorry but anonymous users cannot %(action)s.<br />\n"
+"            Please login or create an account <a href'%(signin_url)s'>here</"
+"a>.\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:47
+#, python-format
+msgid ""
+"\n"
+"            Sorry, but you don't have enough %(action)s left for today..<br /"
+">\n"
+"            The limit is %(limit)s per day..<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:57
+#, python-format
+msgid ""
+"\n"
+"            Sorry, but you cannot %(action)s twice the same post.<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:71 forum/views/commands.py:74
+#: forum/views/commands.py:111
+msgid "vote"
+msgid_plural "votes"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/views/commands.py:89
+#, python-format
+msgid ""
+"Sorry but you cannot cancel a vote after %(ndays)d %(tdays)s from the "
+"original vote"
+msgstr ""
+
+#: forum/views/commands.py:90
+msgid "day"
+msgid_plural "days"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/views/commands.py:110
+#, python-format
+msgid "You have %(nvotes)s %(tvotes)s left today."
+msgstr ""
+
+#: forum/views/commands.py:121 forum/views/commands.py:127
+msgid "flag posts"
+msgstr ""
+
+#: forum/views/commands.py:132
+msgid "flags"
+msgstr ""
+
+#: forum/views/commands.py:149 forum/views/commands.py:155
+msgid "like comments"
+msgstr ""
+
+#: forum/views/commands.py:152
+msgid "like"
+msgstr ""
+
+#: forum/views/commands.py:179 forum/views/commands.py:182
+msgid "delete comments"
+msgstr ""
+
+#: forum/views/commands.py:197
+msgid "mark a question as favorite"
+msgstr ""
+
+#: forum/views/commands.py:221 forum/views/commands.py:233
+msgid "comment"
+msgstr ""
+
+#: forum/views/commands.py:224 forum/views/commands.py:351
+msgid "Invalid request"
+msgstr ""
+
+#: forum/views/commands.py:230
+msgid "edit comments"
+msgstr ""
+
+#: forum/views/commands.py:240
+msgid "Comment is empty"
+msgstr ""
+
+#: forum/views/commands.py:265
+msgid "accept answers"
+msgstr ""
+
+#: forum/views/commands.py:271
+msgid "Sorry but only the question author can accept an answer"
+msgstr ""
+
+#: forum/views/commands.py:295 forum/views/commands.py:298
+msgid "delete posts"
+msgstr ""
+
+#: forum/views/meta.py:43
+#, python-format
+msgid "Feedback message from %(site_name)s"
+msgstr ""
+
+#: forum/views/meta.py:46
+msgid "Thanks for the feedback!"
+msgstr ""
+
+#: forum/views/meta.py:53
+msgid "We look forward to hearing your feedback! Please, give it next time :)"
+msgstr ""
+
+#: forum/views/readers.py:64
+msgid "Open questions without an accepted answer"
+msgstr ""
+
+#: forum/views/readers.py:73
+#, python-format
+msgid "Questions tagged <span class=\"tag\">%(tag)s</span>"
+msgstr ""
+
+#: forum/views/readers.py:131
+#, python-format
+msgid "questions matching '%(keywords)s'"
+msgstr ""
+
+#: forum/views/users.py:152
+msgid "user profile"
+msgstr ""
+
+#: forum/views/users.py:152
+msgid "user profile overview"
+msgstr ""
+
+#: forum/views/users.py:186
+msgid "recent user activity"
+msgstr ""
+
+#: forum/views/users.py:186
+msgid "profile - recent activity"
+msgstr ""
+
+#: forum/views/users.py:196
+msgid "profile - votes"
+msgstr ""
+
+#: forum/views/users.py:203
+msgid "user reputation in the community"
+msgstr ""
+
+#: forum/views/users.py:203
+msgid "profile - user reputation"
+msgstr ""
+
+#: forum/views/users.py:214
+msgid "favorite questions"
+msgstr ""
+
+#: forum/views/users.py:214
+msgid "profile - favorite questions"
+msgstr ""
+
+#: forum/views/users.py:220
+msgid "subscription settings"
+msgstr ""
+
+#: forum/views/users.py:220
+msgid "profile - subscriptions"
+msgstr ""
+
+#: forum/views/users.py:230
+msgid "Notifications are now enabled"
+msgstr ""
+
+#: forum/views/users.py:232
+msgid "Notifications are now disabled"
+msgstr ""
+
+#: forum/views/users.py:239
+msgid "New subscription settings are now saved"
+msgstr ""
+
+#: forum/views/writers.py:68
+msgid "uploading images is limited to users with >60 reputation points"
+msgstr ""
+
+#: forum/views/writers.py:70
+msgid "allowed file types are 'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'"
+msgstr ""
+
+#: forum/views/writers.py:72
+#, python-format
+msgid "maximum upload file size is %sM"
+msgstr ""
+
+#: forum/views/writers.py:74
+#, python-format
+msgid ""
+"Error uploading file. Please contact the site administrator. Thank you. %s"
+msgstr ""
+
+#: forum/views/writers.py:85
+msgid "Initial revision"
+msgstr ""
+
+#: forum/views/writers.py:143
+msgid "Retag"
+msgstr ""
+
+#: forum_modules/books/urls.py:7 forum_modules/books/urls.py:8
+#: forum_modules/books/urls.py:9
+msgid "books/"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:17
+#: forum_modules/default_badges/badges.py:24
+#: forum_modules/default_badges/badges.py:31
+#, python-format
+msgid "Asked a question with %s views"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:39
+#: forum_modules/default_badges/badges.py:53
+#: forum_modules/default_badges/badges.py:67
+#, python-format
+msgid "Answer voted up %s times"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:46
+#: forum_modules/default_badges/badges.py:60
+#: forum_modules/default_badges/badges.py:74
+#, python-format
+msgid "Question voted up %s times"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:82
+#: forum_modules/default_badges/badges.py:89
+#, python-format
+msgid "Question favorited by %s users"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:97
+#, python-format
+msgid "Deleted own post with score of %s or higher"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:108
+#, python-format
+msgid "Deleted own post with score of %s or lower"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:120
+msgid "First flagged post"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:127
+msgid "First down vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:134
+msgid "First retag"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:141
+msgid "First up vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:148
+msgid "First edit"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:155
+msgid "First accepted answer on your own question"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:162
+msgid "Completed all user profile fields"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:169
+msgid "First rollback"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:177
+#, python-format
+msgid "Voted %s times"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:184
+#, python-format
+msgid "Left %s comments"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:192
+#, python-format
+msgid "Answered your own question with at least %s up votes"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:205
+msgid "Strunk & White"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:206
+#, python-format
+msgid "Edited %s entries"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:217
+msgid "Asked first question with at least one up vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:228
+msgid "Answered first question with at least one up vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:260
+#, python-format
+msgid "First answer was accepted with at least %s up votes"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:271
+#, python-format
+msgid "Accepted answer and voted up %s times"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:282
+#, python-format
+msgid ""
+"Answered a question more than %(dif_days)s days later with at least %"
+"(up_votes)s votes"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:295
+#, python-format
+msgid "Created a tag used by %s questions"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:6
+msgid "Popular Question views"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:7
+msgid ""
+"\n"
+"Number of question views required to award a Popular Question badge to the "
+"question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:12
+msgid "Notable Question views"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:13
+msgid ""
+"\n"
+"Number of question views required to award a Notable Question badge to the "
+"question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:18
+msgid "Famous Question views"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:19
+msgid ""
+"\n"
+"Number of question views required to award a Famous Question badge to the "
+"question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:24
+msgid "Nice Answer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:25
+msgid ""
+"\n"
+"Number of up votes required to award a Nice Answer badge to the answer "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:30
+msgid "Nice Question up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:31
+msgid ""
+"\n"
+"Number of up votes required to award a Nice Question badge to the question "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:36
+msgid "Good Answer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:37
+msgid ""
+"\n"
+"Number of up votes required to award a Good Answer badge to the answer "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:42
+msgid "Good Question up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:43
+msgid ""
+"\n"
+"Number of up votes required to award a Good Question badge to the question "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:48
+msgid "Great Answer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:49
+msgid ""
+"\n"
+"Number of up votes required to award a Great Answer badge to the answer "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:54
+msgid "Great Question up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:55
+msgid ""
+"\n"
+"Number of up votes required to award a Great Question badge to the question "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:60
+msgid "Favorite Question favorite count"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:61
+msgid ""
+"\n"
+"How many times a question needs to be favorited by other users to award a "
+"Favorite Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:66
+msgid "Stellar Question favorite count"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:67
+msgid ""
+"\n"
+"How many times a question needs to be favorited by other users to award a "
+"Stellar Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:72
+msgid "Disciplined minimum score"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:73
+msgid ""
+"\n"
+"Minimum score a question needs to have to award the Disciplined badge to an "
+"author of a question who deletes it.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:78
+msgid "Peer Pressure maximum score"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:79
+msgid ""
+"\n"
+"Maximum score a question needs to have to award the Peer Pressure badge to "
+"an author of a question who deletes it.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:84
+msgid "Civic Duty votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:85
+msgid ""
+"\n"
+"Number of votes an user needs to cast to be awarded the Civic Duty badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:90
+msgid "Pundit number of comments"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:91
+msgid ""
+"\n"
+"Number of comments an user needs to post to be awarded the Pundit badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:96
+msgid "Self Learner up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:97
+msgid ""
+"\n"
+"Number of up votes an answer from the question author needs to have for the "
+"author to be awarded the Self Learner badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:102
+msgid "Strunk and White updates"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:103
+msgid ""
+"\n"
+"Number of question or answer updates an user needs to make to be awarded the "
+"Strunk & White badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:108
+msgid "Enlightened up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:109
+msgid ""
+"\n"
+"Number of up votes an accepted answer needs to have for the author to be "
+"awarded the Enlightened badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:114
+msgid "Guru up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:115
+msgid ""
+"\n"
+"Number of up votes an accepted answer needs to have for the author to be "
+"awarded the Guru badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:120
+msgid "Necromancer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:121
+msgid ""
+"\n"
+"Number of up votes an answer needs to have for the author to be awarded the "
+"Necromancer badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:126
+msgid "Necromancer difference in days"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:127
+msgid ""
+"\n"
+"Difference in days betwen the posted date of a question and an answer for "
+"the answer author to be awarded the Necromancer badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:132
+msgid "Taxonomist usage count"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:133
+msgid ""
+"\n"
+"How many usages a tag needs to have for the tag creator to be awarded the "
+"Taxonomist badge. \n"
+msgstr ""
+
+#: forum_modules/facebookauth/authentication.py:31
+msgid "Sorry, your Facebook session has expired, please try again"
+msgstr ""
+
+#: forum_modules/facebookauth/authentication.py:33
+msgid ""
+"The authentication with Facebook connect failed due to an invalid signature"
+msgstr ""
+
+#: forum_modules/facebookauth/authentication.py:35
+msgid ""
+"The authentication with Facebook connect failed, cannot find authentication "
+"tokens"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:75
+msgid "Please enter valid username and password (both are case-sensitive)."
+msgstr ""
+
+#: forum_modules/localauth/forms.py:79
+msgid "This account is inactive."
+msgstr ""
+
+#: forum_modules/localauth/forms.py:81
+msgid "Login failed."
+msgstr ""
+
+#: forum_modules/localauth/forms.py:85
+msgid "This user is not a valid user"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:88
+msgid "Please enter username and password"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:90
+msgid "Please enter your password"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:92
+msgid "Please enter user name"
+msgstr ""
+
+#: forum_modules/localauth/urls.py:7
+msgid "local/"
+msgstr ""
+
+#: forum_modules/localauth/views.py:33
+msgid "A validation email has been sent to your email address. "
+msgstr ""
+
+#: forum_modules/oauthauth/consumer.py:33
+msgid "Error, the oauth token is not on the server"
+msgstr ""
+
+#: forum_modules/oauthauth/consumer.py:38
+msgid "Something went wrong! Auth tokens do not match"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:40
+msgid "Sorry, but your input is not a valid OpenId"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:92
+msgid "The OpenId authentication request was canceled"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:94
+msgid "The OpenId authentication failed: "
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:96
+msgid "Setup needed"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:98
+msgid "The OpenId authentication failed with an unknown status: "
+msgstr ""
+
+#: forum_modules/openidauth/templates/openidurl.html:7
+msgid "Enter your OpenId Url"
+msgstr ""
+
+#: forum_modules/project_badges/badges.py:9
+#, python-format
+msgid "Got %s upvotes in a question tagged with \"bug\""
+msgstr ""
+
+#: forum_modules/recaptcha/formfield.py:20
+msgid "Invalid captcha"
+msgstr ""
+
+#: forum_modules/sximporter/importer.py:39
+#, python-format
+msgid "Unknown user %(number)d"
+msgstr ""
+
+#: forum_modules/sximporter/urls.py:8
+msgid "sximporter/"
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:7
+msgid "SX Importer"
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:10
+msgid "Welcome to Stack Exchange dump importer."
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:16
+msgid "Your user id in stack exchange"
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:20
+msgid "Merge users with same user name and email"
+msgstr ""
+
+#: locale/phrases.py:1
+msgid "Test Phrase 1"
+msgstr ""
+
+#: locale/phrases.py:2
+msgid "Test Phrase 2"
+msgstr ""
+
+#: locale/phrases.py:3
+msgid "Test Phrase 3"
+msgstr ""
+
+#: locale/phrases.py:4
+msgid "Test Phrase n"
+msgstr ""
diff --git a/forum/modules/template_loader.py/locale/phrases.py b/forum/modules/template_loader.py/locale/phrases.py
new file mode 100644 (file)
index 0000000..be378cc
--- /dev/null
@@ -0,0 +1,4 @@
+_("Test Phrase 1")
+_("Test Phrase 2")
+_("Test Phrase 3")
+_("Test Phrase n")
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/locale/pt/LC_MESSAGES/django.mo b/forum/modules/template_loader.py/locale/pt/LC_MESSAGES/django.mo
new file mode 100644 (file)
index 0000000..345109f
Binary files /dev/null and b/forum/modules/template_loader.py/locale/pt/LC_MESSAGES/django.mo differ
diff --git a/forum/modules/template_loader.py/locale/pt/LC_MESSAGES/django.po b/forum/modules/template_loader.py/locale/pt/LC_MESSAGES/django.po
new file mode 100644 (file)
index 0000000..7a76e84
--- /dev/null
@@ -0,0 +1,4446 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-04-28 16:53-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"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: forum/const.py:8
+msgid "duplicate question"
+msgstr ""
+
+#: forum/const.py:9
+msgid "question is off-topic or not relevant"
+msgstr ""
+
+#: forum/const.py:10
+msgid "too subjective and argumentative"
+msgstr ""
+
+#: forum/const.py:11
+msgid "is not an answer to the question"
+msgstr ""
+
+#: forum/const.py:12
+msgid "the question is answered, right answer was accepted"
+msgstr ""
+
+#: forum/const.py:13
+msgid "problem is not reproducible or outdated"
+msgstr ""
+
+#: forum/const.py:14
+msgid "question contains offensive inappropriate, or malicious remarks"
+msgstr ""
+
+#: forum/const.py:15
+msgid "spam or advertising"
+msgstr ""
+
+#: forum/const.py:71 forum/skins/default/templates/osqaadmin/index.html:21
+msgid "question"
+msgstr ""
+
+#: forum/const.py:72 forum/skins/default/templates/book.html:110
+#: forum/skins/default/templates/osqaadmin/index.html:26
+msgid "answer"
+msgstr ""
+
+#: forum/const.py:73
+msgid "commented question"
+msgstr ""
+
+#: forum/const.py:74
+msgid "commented answer"
+msgstr ""
+
+#: forum/const.py:75
+msgid "edited question"
+msgstr ""
+
+#: forum/const.py:76
+msgid "edited answer"
+msgstr ""
+
+#: forum/const.py:77
+msgid "received award"
+msgstr ""
+
+#: forum/const.py:78
+msgid "marked best answer"
+msgstr ""
+
+#: forum/const.py:79
+msgid "upvoted"
+msgstr ""
+
+#: forum/const.py:80
+msgid "downvoted"
+msgstr ""
+
+#: forum/const.py:81
+msgid "upvote canceled"
+msgstr ""
+
+#: forum/const.py:82
+msgid "downvote canceled"
+msgstr ""
+
+#: forum/const.py:83
+msgid "deleted question"
+msgstr ""
+
+#: forum/const.py:84
+msgid "deleted answer"
+msgstr ""
+
+#: forum/const.py:85
+msgid "marked offensive"
+msgstr ""
+
+#: forum/const.py:86
+msgid "updated tags"
+msgstr ""
+
+#: forum/const.py:87
+msgid "selected favorite"
+msgstr ""
+
+#: forum/const.py:88
+msgid "completed user profile"
+msgstr ""
+
+#: forum/const.py:89
+msgid "email update sent to user"
+msgstr ""
+
+#: forum/const.py:93
+msgid "question_answered"
+msgstr ""
+
+#: forum/const.py:94
+msgid "question_commented"
+msgstr ""
+
+#: forum/const.py:95
+msgid "answer_commented"
+msgstr ""
+
+#: forum/const.py:96
+msgid "answer_accepted"
+msgstr ""
+
+#: forum/const.py:100
+msgid "[closed]"
+msgstr ""
+
+#: forum/const.py:101
+msgid "[deleted]"
+msgstr ""
+
+#: forum/const.py:102
+msgid "initial version"
+msgstr ""
+
+#: forum/const.py:103
+msgid "retagged"
+msgstr ""
+
+#: forum/const.py:111
+msgid "Instantly"
+msgstr ""
+
+#: forum/const.py:112
+msgid "Daily"
+msgstr ""
+
+#: forum/const.py:113
+msgid "Weekly"
+msgstr ""
+
+#: forum/const.py:114
+msgid "No notifications"
+msgstr ""
+
+#: forum/feed.py:18
+msgid " - "
+msgstr ""
+
+#: forum/feed.py:18
+msgid "latest questions"
+msgstr ""
+
+#: forum/forms.py:21 forum/skins/default/templates/answer_edit_tips.html:35
+#: forum/skins/default/templates/answer_edit_tips.html:39
+#: forum/skins/default/templates/question_edit_tips.html:37
+#: forum/skins/default/templates/question_edit_tips.html:42
+msgid "title"
+msgstr ""
+
+#: forum/forms.py:22
+msgid "please enter a descriptive title for your question"
+msgstr ""
+
+#: forum/forms.py:27
+msgid "title must be > 10 characters"
+msgstr ""
+
+#: forum/forms.py:36
+msgid "content"
+msgstr ""
+
+#: forum/forms.py:42
+msgid "question content must be > 10 characters"
+msgstr ""
+
+#: forum/forms.py:52 forum/skins/default/templates/header.html:31
+#: forum/skins/default/templates/header.html:56
+msgid "tags"
+msgstr ""
+
+#: forum/forms.py:54
+msgid ""
+"Tags are short keywords, with no spaces within. Up to five tags can be used."
+msgstr ""
+
+#: forum/forms.py:61 forum/skins/default/templates/question_retag.html:43
+msgid "tags are required"
+msgstr ""
+
+#: forum/forms.py:67
+msgid "please use 5 tags or less"
+msgstr ""
+
+#: forum/forms.py:72
+msgid "tags must be shorter than 20 characters"
+msgstr ""
+
+#: forum/forms.py:74
+msgid ""
+"please use following characters in tags: letters 'a-z', numbers, and "
+"characters '.-_#'"
+msgstr ""
+
+#: forum/forms.py:84
+#: forum/skins/default/templates/post_contributor_info.html:7
+#: forum/skins/default/templates/question_summary_list_roll.html:26
+#: forum/skins/default/templates/question_summary_list_roll.html:38
+msgid "community wiki"
+msgstr ""
+
+#: forum/forms.py:85
+msgid ""
+"if you choose community wiki option, the question and answer do not generate "
+"points and name of author will not be shown"
+msgstr ""
+
+#: forum/forms.py:101
+msgid "update summary:"
+msgstr ""
+
+#: forum/forms.py:102
+msgid ""
+"enter a brief summary of your revision (e.g. fixed spelling, grammar, "
+"improved style, this field is optional)"
+msgstr ""
+
+#: forum/forms.py:105
+msgid "Automatically accept user's contributions for the email updates"
+msgstr ""
+
+#: forum/forms.py:118
+msgid "Your name:"
+msgstr ""
+
+#: forum/forms.py:119
+msgid "Email (not shared with anyone):"
+msgstr ""
+
+#: forum/forms.py:120
+msgid "Your message:"
+msgstr ""
+
+#: forum/forms.py:202
+msgid "this email does not have to be linked to gravatar"
+msgstr ""
+
+#: forum/forms.py:204
+msgid "Screen name"
+msgstr ""
+
+#: forum/forms.py:205
+msgid "Real name"
+msgstr ""
+
+#: forum/forms.py:206
+msgid "Website"
+msgstr ""
+
+#: forum/forms.py:207
+msgid "Location"
+msgstr ""
+
+#: forum/forms.py:208
+msgid "Date of birth"
+msgstr ""
+
+#: forum/forms.py:208
+msgid "will not be shown, used to calculate age, format: YYYY-MM-DD"
+msgstr ""
+
+#: forum/forms.py:209 forum/skins/default/templates/account_settings.html:21
+msgid "Profile"
+msgstr ""
+
+#: forum/forms.py:240 forum/forms.py:241
+msgid "this email has already been registered, please use another one"
+msgstr ""
+
+#: forum/subscriptions.py:41
+#, python-format
+msgid "New question on %(app_name)s"
+msgstr ""
+
+#: forum/subscriptions.py:73
+#, python-format
+msgid "New answer to '%(question_title)s'"
+msgstr ""
+
+#: forum/subscriptions.py:112
+#, python-format
+msgid "New comment on %(question_title)s"
+msgstr ""
+
+#: forum/subscriptions.py:136
+#, python-format
+msgid "An answer to '%(question_title)s' was accepted"
+msgstr ""
+
+#: forum/subscriptions.py:156
+#, python-format
+msgid "%(username)s is a new member on %(app_name)s"
+msgstr ""
+
+#: forum/urls.py:44
+msgid "upfiles/"
+msgstr ""
+
+#: forum/urls.py:49
+msgid "about/"
+msgstr ""
+
+#: forum/urls.py:50
+msgid "faq/"
+msgstr ""
+
+#: forum/urls.py:51
+msgid "privacy/"
+msgstr ""
+
+#: forum/urls.py:52
+msgid "logout/"
+msgstr ""
+
+#: forum/urls.py:53 forum/urls.py:54
+msgid "answers/"
+msgstr ""
+
+#: forum/urls.py:53 forum/urls.py:58 forum/urls.py:98
+#: forum/skins/default/templates/users/info.html:44
+msgid "edit/"
+msgstr ""
+
+#: forum/urls.py:54 forum/urls.py:74
+msgid "revisions/"
+msgstr ""
+
+#: forum/urls.py:55 forum/urls.py:56 forum/urls.py:57 forum/urls.py:58
+#: forum/urls.py:59 forum/urls.py:60 forum/urls.py:61 forum/urls.py:74
+msgid "questions/"
+msgstr ""
+
+#: forum/urls.py:56 forum_modules/books/urls.py:8
+msgid "ask/"
+msgstr ""
+
+#: forum/urls.py:57
+msgid "unanswered/"
+msgstr ""
+
+#: forum/urls.py:59
+msgid "close/"
+msgstr ""
+
+#: forum/urls.py:60
+msgid "reopen/"
+msgstr ""
+
+#: forum/urls.py:61
+msgid "answer/"
+msgstr ""
+
+#: forum/urls.py:63
+msgid "vote/"
+msgstr ""
+
+#: forum/urls.py:64
+msgid "like_comment/"
+msgstr ""
+
+#: forum/urls.py:65
+msgid "comment/"
+msgstr ""
+
+#: forum/urls.py:66
+msgid "delete_comment/"
+msgstr ""
+
+#: forum/urls.py:67
+msgid "accept_answer/"
+msgstr ""
+
+#: forum/urls.py:68
+msgid "mark_favorite/"
+msgstr ""
+
+#: forum/urls.py:69
+msgid "flag/"
+msgstr ""
+
+#: forum/urls.py:70
+msgid "delete/"
+msgstr ""
+
+#: forum/urls.py:71
+msgid "subscribe/"
+msgstr ""
+
+#: forum/urls.py:72
+msgid "matching_tags/"
+msgstr ""
+
+#: forum/urls.py:75
+msgid "command/"
+msgstr ""
+
+#: forum/urls.py:78
+msgid "question/"
+msgstr ""
+
+#: forum/urls.py:79 forum/urls.py:80
+msgid "tags/"
+msgstr ""
+
+#: forum/urls.py:82 forum/urls.py:86
+msgid "mark-tag/"
+msgstr ""
+
+#: forum/urls.py:82
+msgid "interesting/"
+msgstr ""
+
+#: forum/urls.py:86
+msgid "ignored/"
+msgstr ""
+
+#: forum/urls.py:90
+msgid "unmark-tag/"
+msgstr ""
+
+#: forum/urls.py:96 forum/urls.py:98 forum/urls.py:100 forum/urls.py:101
+#: forum/urls.py:102 forum/urls.py:103 forum/urls.py:104 forum/urls.py:105
+#: forum/models/user.py:124
+msgid "users/"
+msgstr ""
+
+#: forum/urls.py:97
+msgid "moderate-user/"
+msgstr ""
+
+#: forum/urls.py:100
+msgid "subscriptions/"
+msgstr ""
+
+#: forum/urls.py:101
+msgid "favorites/"
+msgstr ""
+
+#: forum/urls.py:102
+msgid "reputation/"
+msgstr ""
+
+#: forum/urls.py:103
+msgid "votes/"
+msgstr ""
+
+#: forum/urls.py:104
+msgid "recent/"
+msgstr ""
+
+#: forum/urls.py:107 forum/urls.py:108
+msgid "badges/"
+msgstr ""
+
+#: forum/urls.py:109
+msgid "messages/"
+msgstr ""
+
+#: forum/urls.py:109
+msgid "markread/"
+msgstr ""
+
+#: forum/urls.py:111
+msgid "nimda/"
+msgstr ""
+
+#: forum/urls.py:113
+msgid "upload/"
+msgstr ""
+
+#: forum/urls.py:114
+msgid "search/"
+msgstr ""
+
+#: forum/urls.py:115
+msgid "feedback/"
+msgstr ""
+
+#: forum/urls.py:119 forum/urls.py:120 forum/urls.py:121 forum/urls.py:122
+#: forum/urls.py:123 forum/urls.py:124 forum/urls.py:125 forum/urls.py:126
+#: forum/urls.py:127 forum/urls.py:128 forum/urls.py:129 forum/urls.py:130
+#: forum_modules/localauth/urls.py:7
+msgid "account/"
+msgstr ""
+
+#: forum/urls.py:119 forum/urls.py:121 forum/urls.py:122
+msgid "signin/"
+msgstr ""
+
+#: forum/urls.py:120
+msgid "signout/"
+msgstr ""
+
+#: forum/urls.py:123
+msgid "done/"
+msgstr ""
+
+#: forum/urls.py:124 forum_modules/localauth/urls.py:7
+msgid "register/"
+msgstr ""
+
+#: forum/urls.py:125
+msgid "validate/"
+msgstr ""
+
+#: forum/urls.py:126 forum/urls.py:127
+msgid "tempsignin/"
+msgstr ""
+
+#: forum/urls.py:128
+msgid "authsettings/"
+msgstr ""
+
+#: forum/urls.py:129 forum/urls.py:130
+msgid "providers/"
+msgstr ""
+
+#: forum/urls.py:129
+msgid "remove/"
+msgstr ""
+
+#: forum/urls.py:130
+msgid "add/"
+msgstr ""
+
+#: forum/urls.py:133 forum/urls.py:134 forum/urls.py:135 forum/urls.py:136
+#: forum/urls.py:137 forum_modules/sximporter/urls.py:8
+msgid "admin/"
+msgstr ""
+
+#: forum/urls.py:134
+msgid "denormalize/"
+msgstr ""
+
+#: forum/urls.py:135
+msgid "go_bootstrap/"
+msgstr ""
+
+#: forum/urls.py:136
+msgid "go_defaults/"
+msgstr ""
+
+#: forum/authentication/forms.py:21
+msgid "Your account email"
+msgstr ""
+
+#: forum/authentication/forms.py:23
+msgid "You cannot leave this field blank"
+msgstr ""
+
+#: forum/authentication/forms.py:24 forum/utils/forms.py:107
+msgid "please enter a valid email address"
+msgstr ""
+
+#: forum/authentication/forms.py:32
+msgid "Sorry, but this email is not on our database."
+msgstr ""
+
+#: forum/authentication/forms.py:40
+msgid "okay, let's try!"
+msgstr ""
+
+#: forum/authentication/forms.py:41
+msgid "no OSQA community email please, thanks"
+msgstr ""
+
+#: forum/authentication/forms.py:44
+msgid "please choose one of the options above"
+msgstr ""
+
+#: forum/authentication/forms.py:51
+msgid "Current password"
+msgstr ""
+
+#: forum/authentication/forms.py:62
+msgid ""
+"Old password is incorrect.                     Please enter the correct "
+"password."
+msgstr ""
+
+#: forum/management/commands/send_email_alerts.py:56
+msgid "Daily digest"
+msgstr ""
+
+#: forum/middleware/anon_user.py:34
+#, python-format
+msgid "First time here? Check out the <a href=\"%s\">FAQ</a>!"
+msgstr ""
+
+#: forum/models/question.py:30
+msgid "[closed] "
+msgstr ""
+
+#: forum/models/question.py:33
+msgid "[deleted] "
+msgstr ""
+
+#: forum/models/repute.py:13 forum/skins/default/templates/badges.html:53
+msgid "gold"
+msgstr ""
+
+#: forum/models/repute.py:14 forum/skins/default/templates/badges.html:61
+msgid "silver"
+msgstr ""
+
+#: forum/models/repute.py:15 forum/skins/default/templates/badges.html:68
+msgid "bronze"
+msgstr ""
+
+#: forum/models/tag.py:28
+msgid "interesting"
+msgstr ""
+
+#: forum/models/tag.py:28
+msgid "ignored"
+msgstr ""
+
+#: forum/models/user.py:255
+#: forum/skins/default/templates/post_contributor_info.html:19
+msgid "asked"
+msgstr ""
+
+#: forum/models/user.py:257
+#: forum/skins/default/templates/post_contributor_info.html:22
+msgid "answered"
+msgstr ""
+
+#: forum/models/user.py:259
+msgid "marked an answer"
+msgstr ""
+
+#: forum/models/user.py:261
+msgid "edited a question"
+msgstr ""
+
+#: forum/models/user.py:263
+msgid "commented a question"
+msgstr ""
+
+#: forum/models/user.py:265
+msgid "commented an answer"
+msgstr ""
+
+#: forum/models/user.py:267
+msgid "edited an answer"
+msgstr ""
+
+#: forum/models/user.py:269
+msgid "received badge"
+msgstr ""
+
+#: forum/settings/__init__.py:20
+msgid "Badges config"
+msgstr ""
+
+#: forum/settings/__init__.py:20
+msgid "Configure badges on your OSQA site."
+msgstr ""
+
+#: forum/settings/basic.py:9
+msgid "Basic Settings"
+msgstr ""
+
+#: forum/settings/basic.py:9
+msgid "The basic settings for your application"
+msgstr ""
+
+#: forum/settings/basic.py:12
+msgid "Application logo"
+msgstr ""
+
+#: forum/settings/basic.py:13
+msgid "Your site main logo."
+msgstr ""
+
+#: forum/settings/basic.py:17
+msgid "Favicon"
+msgstr ""
+
+#: forum/settings/basic.py:18
+msgid "Your site favicon."
+msgstr ""
+
+#: forum/settings/basic.py:22
+msgid "Application title"
+msgstr ""
+
+#: forum/settings/basic.py:23
+msgid "The title of your application that will show in the browsers title bar"
+msgstr ""
+
+#: forum/settings/basic.py:26
+msgid "Application short name"
+msgstr ""
+
+#: forum/settings/basic.py:30
+msgid "Application keywords"
+msgstr ""
+
+#: forum/settings/basic.py:31
+msgid "The meta keywords that will be available through the HTML meta tags."
+msgstr ""
+
+#: forum/settings/basic.py:34
+msgid "Application description"
+msgstr ""
+
+#: forum/settings/basic.py:35
+msgid "The description of your application"
+msgstr ""
+
+#: forum/settings/basic.py:39
+msgid "Application intro"
+msgstr ""
+
+#: forum/settings/basic.py:40
+msgid ""
+"The introductory page that is visible in the sidebar for anonymous users."
+msgstr ""
+
+#: forum/settings/basic.py:44
+msgid "Copyright notice"
+msgstr ""
+
+#: forum/settings/basic.py:45
+msgid "The copyright notice visible at the footer of your page."
+msgstr ""
+
+#: forum/settings/basic.py:48
+msgid "Maximum length of comment"
+msgstr ""
+
+#: forum/settings/basic.py:49
+msgid "The maximum length a user can enter for a comment."
+msgstr ""
+
+#: forum/settings/email.py:5
+msgid "Email Settings"
+msgstr ""
+
+#: forum/settings/email.py:5
+msgid "Email server and other email related settings."
+msgstr ""
+
+#: forum/settings/email.py:8
+msgid "Email Server"
+msgstr ""
+
+#: forum/settings/email.py:9
+msgid "The SMTP server through which your application will be sending emails."
+msgstr ""
+
+#: forum/settings/email.py:13
+msgid "Email Port"
+msgstr ""
+
+#: forum/settings/email.py:14
+msgid ""
+"The port on which your SMTP server is listening to. Usually this is 25, but "
+"can be something else."
+msgstr ""
+
+#: forum/settings/email.py:18
+msgid "Email User"
+msgstr ""
+
+#: forum/settings/email.py:19
+msgid "The username for your SMTP connection."
+msgstr ""
+
+#: forum/settings/email.py:23
+msgid "Email Password"
+msgstr ""
+
+#: forum/settings/email.py:24
+msgid "The password for your SMTP connection."
+msgstr ""
+
+#: forum/settings/email.py:29
+msgid "Use TLS"
+msgstr ""
+
+#: forum/settings/email.py:30
+msgid "Does your SMTP server usFes TLS for authentication."
+msgstr ""
+
+#: forum/settings/email.py:34
+msgid "Site 'from' email address"
+msgstr ""
+
+#: forum/settings/email.py:35
+msgid ""
+"The address that will show up on the 'from' field on emails sent by your "
+"website."
+msgstr ""
+
+#: forum/settings/email.py:39
+msgid "Email subject prefix"
+msgstr ""
+
+#: forum/settings/email.py:40
+msgid ""
+"Every email sent through your website will have the subject prefixed by this "
+"string. It's usually a good idea to have such a prefix so your users can "
+"easilly set up a filter on their email clients."
+msgstr ""
+
+#: forum/settings/extkeys.py:4
+msgid "External Keys"
+msgstr ""
+
+#: forum/settings/extkeys.py:4
+msgid ""
+"Keys for various external providers that your application may optionally use."
+msgstr ""
+
+#: forum/settings/extkeys.py:7
+msgid "Google sitemap code"
+msgstr ""
+
+#: forum/settings/extkeys.py:8
+msgid ""
+"This is the code you get when you register your site at <a href='https://www."
+"google.com/webmasters/tools/'>Google webmaster central</a>."
+msgstr ""
+
+#: forum/settings/extkeys.py:12
+msgid "Google analytics key"
+msgstr ""
+
+#: forum/settings/extkeys.py:13
+msgid ""
+"Your Google analytics key. You can get one at the <a href='http://www.google."
+"com/analytics/'>Google analytics official website</a>"
+msgstr ""
+
+#: forum/settings/forms.py:40
+msgid "Change this:"
+msgstr ""
+
+#: forum/settings/minrep.py:4
+msgid "Minimum reputation config"
+msgstr ""
+
+#: forum/settings/minrep.py:4
+msgid ""
+"Configure the minimum reputation required to perform certain actions on your "
+"site."
+msgstr ""
+
+#: forum/settings/minrep.py:7
+msgid "Minimum reputation to vote up"
+msgstr ""
+
+#: forum/settings/minrep.py:8
+msgid "The minimum reputation an user must have to be allowed to vote up."
+msgstr ""
+
+#: forum/settings/minrep.py:11
+msgid "Minimum reputation to vote down"
+msgstr ""
+
+#: forum/settings/minrep.py:12
+msgid "The minimum reputation an user must have to be allowed to vote down."
+msgstr ""
+
+#: forum/settings/minrep.py:15
+msgid "Minimum reputation to flag a post"
+msgstr ""
+
+#: forum/settings/minrep.py:16
+msgid "The minimum reputation an user must have to be allowed to flag a post."
+msgstr ""
+
+#: forum/settings/minrep.py:19
+msgid "Minimum reputation to comment"
+msgstr ""
+
+#: forum/settings/minrep.py:20
+msgid ""
+"The minimum reputation an user must have to be allowed to comment a post."
+msgstr ""
+
+#: forum/settings/minrep.py:23
+msgid "Minimum reputation to like a comment"
+msgstr ""
+
+#: forum/settings/minrep.py:24
+msgid ""
+"The minimum reputation an user must have to be allowed to \"like\" a comment."
+msgstr ""
+
+#: forum/settings/minrep.py:27
+msgid "Minimum reputation to upload"
+msgstr ""
+
+#: forum/settings/minrep.py:28
+msgid ""
+"The minimum reputation an user must have to be allowed to upload a file."
+msgstr ""
+
+#: forum/settings/minrep.py:31
+msgid "Minimum reputation to close own question"
+msgstr ""
+
+#: forum/settings/minrep.py:32
+msgid ""
+"The minimum reputation an user must have to be allowed to close his own "
+"question."
+msgstr ""
+
+#: forum/settings/minrep.py:35
+msgid "Minimum reputation to reopen own question"
+msgstr ""
+
+#: forum/settings/minrep.py:36
+msgid ""
+"The minimum reputation an user must have to be allowed to reopen his own "
+"question."
+msgstr ""
+
+#: forum/settings/minrep.py:39
+msgid "Minimum reputation to retag others questions"
+msgstr ""
+
+#: forum/settings/minrep.py:40
+msgid ""
+"The minimum reputation an user must have to be allowed to retag others "
+"questions."
+msgstr ""
+
+#: forum/settings/minrep.py:43
+msgid "Minimum reputation to edit wiki posts"
+msgstr ""
+
+#: forum/settings/minrep.py:44
+msgid ""
+"The minimum reputation an user must have to be allowed to edit community "
+"wiki posts."
+msgstr ""
+
+#: forum/settings/minrep.py:47
+msgid "Minimum reputation to edit others posts"
+msgstr ""
+
+#: forum/settings/minrep.py:48
+msgid ""
+"The minimum reputation an user must have to be allowed to edit others posts."
+msgstr ""
+
+#: forum/settings/minrep.py:51
+msgid "Minimum reputation to close others posts"
+msgstr ""
+
+#: forum/settings/minrep.py:52
+msgid ""
+"The minimum reputation an user must have to be allowed to close others posts."
+msgstr ""
+
+#: forum/settings/minrep.py:55
+msgid "Minimum reputation to delete comments"
+msgstr ""
+
+#: forum/settings/minrep.py:56
+msgid ""
+"The minimum reputation an user must have to be allowed to delete comments."
+msgstr ""
+
+#: forum/settings/minrep.py:59
+msgid "Minimum reputation to view offensive flags"
+msgstr ""
+
+#: forum/settings/minrep.py:60
+msgid "The minimum reputation an user must have to view offensive flags."
+msgstr ""
+
+#: forum/settings/repgain.py:4
+msgid "Reputation gains and losses config"
+msgstr ""
+
+#: forum/settings/repgain.py:4
+msgid ""
+"Configure the reputation points a user may gain or lose upon certain actions."
+msgstr ""
+
+#: forum/settings/repgain.py:7
+msgid "Initial reputation"
+msgstr ""
+
+#: forum/settings/repgain.py:8
+msgid "The initial reputation an user gets when he first signs in."
+msgstr ""
+
+#: forum/settings/repgain.py:12
+msgid "Maximum reputation a user can gain in one day for being upvoted."
+msgstr ""
+
+#: forum/settings/repgain.py:15
+msgid "Rep gain by upvoted"
+msgstr ""
+
+#: forum/settings/repgain.py:16
+msgid "Reputation a user gains for having one of his posts up voted."
+msgstr ""
+
+#: forum/settings/repgain.py:19
+msgid "Rep lost bu upvote canceled"
+msgstr ""
+
+#: forum/settings/repgain.py:20
+msgid ""
+"Reputation a user loses for having one of the upvotes on his posts canceled."
+msgstr ""
+
+#: forum/settings/repgain.py:23
+msgid "Rep lost by downvoted"
+msgstr ""
+
+#: forum/settings/repgain.py:24
+msgid "Reputation a user loses for having one of his posts down voted."
+msgstr ""
+
+#: forum/settings/repgain.py:27
+msgid "Rep lost by downvoting"
+msgstr ""
+
+#: forum/settings/repgain.py:28
+msgid "Reputation a user loses for down voting a post."
+msgstr ""
+
+#: forum/settings/repgain.py:31
+msgid "Rep gain by downvote canceled"
+msgstr ""
+
+#: forum/settings/repgain.py:32
+msgid ""
+"Reputation a user gains for having one of the downvotes on his posts "
+"canceled."
+msgstr ""
+
+#: forum/settings/repgain.py:35
+msgid "Rep gain by canceling downvote"
+msgstr ""
+
+#: forum/settings/repgain.py:36
+msgid "Reputation a user gains for canceling a downvote."
+msgstr ""
+
+#: forum/settings/repgain.py:39
+msgid "Rep gain by accepted answer"
+msgstr ""
+
+#: forum/settings/repgain.py:40
+msgid "Reputation a user gains for having one of his answers accepted."
+msgstr ""
+
+#: forum/settings/repgain.py:43
+msgid "Rep lost by accepted canceled"
+msgstr ""
+
+#: forum/settings/repgain.py:44
+msgid ""
+"Reputation a user loses for having one of his accepted answers canceled."
+msgstr ""
+
+#: forum/settings/repgain.py:47
+msgid "Rep gain by accepting answer"
+msgstr ""
+
+#: forum/settings/repgain.py:48
+msgid ""
+"Reputation a user gains for accepting an answer to one of his questions."
+msgstr ""
+
+#: forum/settings/repgain.py:51
+msgid "Rep lost by canceling accepted"
+msgstr ""
+
+#: forum/settings/repgain.py:52
+msgid "Reputation a user loses by canceling an accepted answer."
+msgstr ""
+
+#: forum/settings/repgain.py:55
+msgid "Rep lost by post flagged"
+msgstr ""
+
+#: forum/settings/repgain.py:56
+msgid "Reputation a user loses by having one of his posts flagged."
+msgstr ""
+
+#: forum/settings/repgain.py:59
+msgid "Rep lost by post flagged and hidden"
+msgstr ""
+
+#: forum/settings/repgain.py:60
+msgid ""
+"Reputation a user loses by having the last revision of one of his posts "
+"flagged the enough number of times to hide the post."
+msgstr ""
+
+#: forum/settings/repgain.py:63
+msgid "Rep lost by post flagged and deleted"
+msgstr ""
+
+#: forum/settings/repgain.py:64
+msgid ""
+"Reputation a user loses by having the last revision of one of his posts "
+"flagged the enough number of times to delete the post."
+msgstr ""
+
+#: forum/settings/upload.py:5
+msgid "File upload settings"
+msgstr ""
+
+#: forum/settings/upload.py:5
+msgid "File uploads related settings."
+msgstr ""
+
+#: forum/settings/upload.py:8
+msgid "Uploaded files folder"
+msgstr ""
+
+#: forum/settings/upload.py:9
+msgid ""
+"The filesystem path where uploaded files will be stored. Please note that "
+"this folder must exist."
+msgstr ""
+
+#: forum/settings/upload.py:12
+msgid "Uploaded files alias"
+msgstr ""
+
+#: forum/settings/upload.py:13
+msgid ""
+"The url alias for uploaded files. Notice that if you change this setting, "
+"you'll need to restart your site."
+msgstr ""
+
+#: forum/settings/upload.py:16
+msgid "Max file size"
+msgstr ""
+
+#: forum/settings/upload.py:17
+msgid "The maximum allowed file size for uploads in mb."
+msgstr ""
+
+#: forum/settings/voting.py:4
+msgid "Voting rules"
+msgstr ""
+
+#: forum/settings/voting.py:4
+msgid "Configure the voting rules on your site."
+msgstr ""
+
+#: forum/settings/voting.py:7
+msgid "Maximum votes per day"
+msgstr ""
+
+#: forum/settings/voting.py:8
+msgid "The maximum number of votes an user can cast per day."
+msgstr ""
+
+#: forum/settings/voting.py:11
+msgid "Start warning about votes left"
+msgstr ""
+
+#: forum/settings/voting.py:12
+msgid "From how many votes left should an user start to be warned about it."
+msgstr ""
+
+#: forum/settings/voting.py:15
+msgid "Maximum flags per day"
+msgstr ""
+
+#: forum/settings/voting.py:16
+msgid "The maximum number of times an can flag a post per day."
+msgstr ""
+
+#: forum/settings/voting.py:19
+msgid "Flag count to hide post"
+msgstr ""
+
+#: forum/settings/voting.py:20
+msgid ""
+"How many times a post needs to be flagged to be hidden from the main page."
+msgstr ""
+
+#: forum/settings/voting.py:23
+msgid "Flag count to delete post"
+msgstr ""
+
+#: forum/settings/voting.py:24
+msgid "How many times a post needs to be flagged to be deleted."
+msgstr ""
+
+#: forum/settings/voting.py:27
+msgid "Days to cancel a vote"
+msgstr ""
+
+#: forum/settings/voting.py:28
+msgid "How many days an user can cancel a vote after he originaly casted it."
+msgstr ""
+
+#: forum/skins/default/templates/404.html:24
+msgid "Sorry, could not find the page you requested."
+msgstr ""
+
+#: forum/skins/default/templates/404.html:26
+msgid "This might have happened for the following reasons:"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:28
+msgid "this question or answer has been deleted;"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:29
+msgid "url has error - please check it;"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:30
+msgid ""
+"the page you tried to visit is protected or you don't have sufficient "
+"points, see"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:31
+msgid "if you believe this error 404 should not have occured, please"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:32
+msgid "report this problem"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:41
+#: forum/skins/default/templates/500.html:27
+msgid "back to previous page"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:42
+msgid "see all questions"
+msgstr ""
+
+#: forum/skins/default/templates/404.html:43
+msgid "see all tags"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:22
+msgid "sorry, system error"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:24
+msgid "system error log is recorded, error will be fixed as soon as possible"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:25
+msgid "please report the error to the site administrators if you wish"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:28
+msgid "see latest questions"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:29
+msgid "see tags"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:12
+#: forum/skins/default/templates/book.html:105
+#: forum/skins/default/templates/question_summary_list_roll.html:14
+#: forum/skins/default/templates/question_list/item.html:10
+#: forum/views/commands.py:82
+msgid "votes"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:14
+msgid "this answer has been accepted to be correct"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:16
+#: forum/skins/default/templates/question_summary_list_roll.html:13
+#: forum/skins/default/templates/question_list/item.html:14
+msgid "answers"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:20
+#: forum/skins/default/templates/book.html:115
+#: forum/skins/default/templates/question_summary_list_roll.html:15
+#: forum/skins/default/templates/question_list/item.html:18
+msgid "views"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:34
+#: forum/skins/default/templates/question.html:234
+#: forum/skins/default/templates/question_summary_list_roll.html:52
+#: forum/skins/default/templates/tags.html:49
+#: forum/skins/default/templates/question_list/item.html:29
+msgid "see questions tagged"
+msgstr ""
+
+#: forum/skins/default/templates/_question_list.html:34
+#: forum/skins/default/templates/book.html:125
+#: forum/skins/default/templates/question.html:234
+#: forum/skins/default/templates/question_summary_list_roll.html:52
+#: forum/skins/default/templates/tags.html:49
+#: forum/skins/default/templates/question_list/item.html:29
+msgid "using tags"
+msgstr ""
+
+#: forum/skins/default/templates/about.html:5
+#: forum/skins/default/templates/about.html:9
+msgid "About"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:4
+msgid "Account functions"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:29
+#: forum/skins/default/templates/auth/auth_settings.html:31
+msgid "Change password"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:30
+msgid "Give your  account a new password."
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:32
+msgid "Change email "
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:33
+msgid "Add or update the email address associated with your account."
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:35
+msgid "Change OpenID"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:36
+msgid "Change openid associated to your account"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:39
+msgid "Delete account"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:40
+msgid "Erase your username and all your data from website"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:5
+#: forum/skins/default/templates/answer_edit.html:39
+msgid "Edit answer"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:18
+#: forum/skins/default/templates/answer_edit.html:21
+#: forum/skins/default/templates/ask.html:19
+#: forum/skins/default/templates/ask.html:22
+#: forum/skins/default/templates/question_edit.html:19
+#: forum/skins/default/templates/question_edit.html:22
+msgid "hide preview"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:21
+#: forum/skins/default/templates/ask.html:22
+#: forum/skins/default/templates/question_edit.html:22
+msgid "show preview"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:39
+#: forum/skins/default/templates/question_edit.html:63
+#: forum/skins/default/templates/question_retag.html:56
+#: forum/skins/default/templates/revisions_answer.html:36
+#: forum/skins/default/templates/revisions_question.html:35
+msgid "back"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:44
+#: forum/skins/default/templates/question_edit.html:68
+#: forum/skins/default/templates/revisions_answer.html:50
+#: forum/skins/default/templates/revisions_question.html:49
+msgid "revision"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:47
+#: forum/skins/default/templates/question_edit.html:72
+msgid "select revision"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:54
+#: forum/skins/default/templates/ask.html:93
+#: forum/skins/default/templates/question.html:184
+#: forum/skins/default/templates/question_edit.html:89
+msgid "Toggle the real time Markdown editor preview"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:54
+#: forum/skins/default/templates/ask.html:93
+#: forum/skins/default/templates/question.html:185
+#: forum/skins/default/templates/question_edit.html:89
+msgid "toggle preview"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:63
+#: forum/skins/default/templates/question_edit.html:115
+#: forum/skins/default/templates/question_retag.html:77
+msgid "Save edit"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:64
+#: forum/skins/default/templates/close.html:29
+#: forum/skins/default/templates/feedback.html:50
+#: forum/skins/default/templates/question_edit.html:116
+#: forum/skins/default/templates/question_retag.html:78
+#: forum/skins/default/templates/reopen.html:30
+#: forum/skins/default/templates/users/edit.html:87
+msgid "Cancel"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:4
+msgid "answer tips"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:7
+msgid "please make your answer relevant to this community"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:10
+msgid "try to give an answer, rather than engage into a discussion"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:13
+msgid "please try to provide details"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:16
+#: forum/skins/default/templates/question_edit_tips.html:18
+msgid "be clear and concise"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:20
+#: forum/skins/default/templates/question_edit_tips.html:22
+msgid "see frequently asked questions"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:26
+#: forum/skins/default/templates/question_edit_tips.html:28
+msgid "Markdown tips"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:29
+#: forum/skins/default/templates/question_edit_tips.html:31
+msgid "*italic* or __italic__"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:32
+#: forum/skins/default/templates/question_edit_tips.html:34
+msgid "**bold** or __bold__"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:35
+#: forum/skins/default/templates/question_edit_tips.html:37
+msgid "link"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:35
+#: forum/skins/default/templates/answer_edit_tips.html:39
+#: forum/skins/default/templates/question_edit_tips.html:37
+#: forum/skins/default/templates/question_edit_tips.html:42
+msgid "text"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:39
+#: forum/skins/default/templates/question_edit_tips.html:42
+msgid "image"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:43
+#: forum/skins/default/templates/question_edit_tips.html:46
+msgid "numbered list:"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:48
+#: forum/skins/default/templates/question_edit_tips.html:51
+msgid "basic HTML tags are also supported"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit_tips.html:52
+#: forum/skins/default/templates/question_edit_tips.html:55
+msgid "learn more about Markdown"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:5
+#: forum/skins/default/templates/ask.html:57
+msgid "Ask a question"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:64
+msgid "login to post question info"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:70
+#, python-format
+msgid ""
+"must have valid %(email)s to post, \n"
+"                            see %(email_validation_faq_url)s\n"
+"                            "
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:108
+msgid "(required)"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:115
+msgid "Login/signup to post your question"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:117
+msgid "Ask your question"
+msgstr ""
+
+#: forum/skins/default/templates/badge.html:6
+#: forum/skins/default/templates/badge.html:17
+msgid "Badge"
+msgstr ""
+
+#: forum/skins/default/templates/badge.html:26
+msgid "The users have been awarded with badges:"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:6
+msgid "Badges summary"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:17
+msgid "Badges"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:21
+msgid "Community gives you awards for your questions, answers and votes."
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:22
+#, python-format
+msgid ""
+"Below is the list of available badges and number \n"
+"    of times each type of badge has been awarded. Give us feedback at %"
+"(feedback_faq_url)s.\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:50
+msgid "Community badges"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:56
+msgid "gold badge description"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:64
+msgid "silver badge description"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:67
+msgid "bronze badge: often given as a special honor"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:71
+msgid "bronze badge description"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:7
+msgid "reading channel"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:26
+msgid "[author]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:30
+msgid "[publisher]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:34
+msgid "[publication date]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:38
+msgid "[price]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:39
+msgid "currency unit"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:42
+msgid "[pages]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:43
+msgid "pages abbreviation"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:46
+msgid "[tags]"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:56
+msgid "author blog"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:62
+msgid "book directory"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:66
+msgid "buy online"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:79
+msgid "reader questions"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:82
+msgid "ask the author"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:88
+#: forum/skins/default/templates/book.html:93
+msgid "this question was selected as favorite"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:88
+#: forum/skins/default/templates/book.html:93
+msgid "number of times"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:108
+msgid "the answer has been accepted to be correct"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:147
+msgid "subscribe to book RSS feed"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:147
+msgid "subscribe to the questions feed"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:6
+#: forum/skins/default/templates/close.html:16
+msgid "Close question"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:19
+msgid "Close the question"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:25
+msgid "Reasons"
+msgstr ""
+
+#: forum/skins/default/templates/close.html:28
+msgid "OK to close"
+msgstr ""
+
+#: forum/skins/default/templates/email_base.html:31
+msgid "home"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:11
+msgid "Frequently Asked Questions "
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:16
+msgid "What kinds of questions can I ask here?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:17
+msgid ""
+"Most importantly - questions should be <strong>relevant</strong> to this "
+"community."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:18
+msgid ""
+"Before asking the question - please make sure to use search to see whether "
+"your question has alredy been answered."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:21
+msgid "What questions should I avoid asking?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:22
+msgid ""
+"Please avoid asking questions that are not relevant to this community, too "
+"subjective and argumentative."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:27
+msgid "What should I avoid in my answers?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:28
+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 ""
+
+#: forum/skins/default/templates/faq.html:32
+msgid "Who moderates this community?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:33
+msgid "The short answer is: <strong>you</strong>."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:34
+msgid "This website is moderated by the users."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:35
+msgid ""
+"The reputation system allows users earn the authorization to perform a "
+"variety of moderation tasks."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:40
+msgid "How does reputation system work?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:41
+msgid "Rep system summary"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:42
+msgid ""
+"For example, if you ask an interesting question or give a helpful answer, "
+"your input will be upvoted. On the other hand if the answer is misleading - "
+"it will be downvoted. Each vote in favor will generate <strong>10</strong> "
+"points, each vote against will subtract <strong>2</strong> points. There is "
+"a limit of <strong>200</strong> points that can be accumulated per question "
+"or answer. The table below explains reputation point requirements for each "
+"type of moderation task."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:53
+#: forum/skins/default/templates/users/votes.html:15
+#: forum/views/commands.py:77
+msgid "upvote"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:57
+msgid "use tags"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:62
+msgid "add comments"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:66
+#: forum/skins/default/templates/users/votes.html:17
+#: forum/views/commands.py:77
+msgid "downvote"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:69
+msgid "open and close own questions"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:73
+msgid "retag questions"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:78
+msgid "edit community wiki questions"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:83
+msgid "edit any answer"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:87
+msgid "open any closed question"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:91
+msgid "delete any comment"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:95
+msgid "delete any questions and answers and perform other moderation tasks"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:103
+msgid "how to validate email title"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:105
+#, python-format
+msgid ""
+"how to validate email info with %(send_email_key_url)s %(gravatar_faq_url)s"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:110
+msgid "what is gravatar"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:111
+msgid "gravatar faq info"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:114
+msgid "To register, do I need to create new password?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:115
+msgid ""
+"No, you don't have to. You can login through any service that supports "
+"OpenID, e.g. Google, Yahoo, AOL, etc."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:116
+msgid "Login now!"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:121
+msgid "Why other people can edit my questions/answers?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:122
+msgid "Goal of this site is..."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:122
+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 ""
+
+#: forum/skins/default/templates/faq.html:123
+msgid "If this approach is not for you, we respect your choice."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:127
+msgid "Still have questions?"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:128
+#, python-format
+msgid ""
+"Please ask your question at %(ask_question_url)s, help make our community "
+"better!"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:130
+#: forum/skins/default/templates/header.html:30
+#: forum/skins/default/templates/header.html:55 forum/views/readers.py:76
+msgid "questions"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:130
+msgid "."
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:6
+msgid "Feedback"
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:11
+msgid "Give us your feedback!"
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:17
+#, python-format
+msgid ""
+"\n"
+"            <span class='big strong'>Dear %(user_name)s</span>, we look "
+"forward to hearing your feedback. \n"
+"            Please type and send us your message below.\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:24
+msgid ""
+"\n"
+"            <span class='big strong'>Dear visitor</span>, we look forward to "
+"hearing your feedback.\n"
+"            Please type and send us your message below.\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:41
+msgid "(this field is required)"
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:49
+msgid "Send Feedback"
+msgstr ""
+
+#: forum/skins/default/templates/footer.html:7
+#: forum/skins/default/templates/header.html:16
+#: forum/skins/default/templates/index.html:12
+msgid "about"
+msgstr ""
+
+#: forum/skins/default/templates/footer.html:8
+#: forum/skins/default/templates/header.html:17
+#: forum/skins/default/templates/index.html:13
+#: forum/skins/default/templates/question_edit_tips.html:22
+msgid "faq"
+msgstr ""
+
+#: forum/skins/default/templates/footer.html:9
+msgid "privacy policy"
+msgstr ""
+
+#: forum/skins/default/templates/footer.html:18
+msgid "give feedback"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:9
+msgid "administration"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:12
+msgid "logout"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:14
+msgid "login"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:24
+msgid "back to home page"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:32
+#: forum/skins/default/templates/header.html:57
+msgid "users"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:33
+#: forum/skins/default/templates/users/signature.html:9
+#: forum/skins/default/templates/users/signature.html:15
+#: forum/skins/default/templates/users/signature.html:21
+#: forum/templatetags/extra_tags.py:167 forum/templatetags/extra_tags.py:196
+msgid "badges"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:34
+msgid "unanswered questions"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:36
+msgid "ask a question"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:51
+msgid "search"
+msgstr ""
+
+#: forum/skins/default/templates/index.html:9
+msgid "welcome to "
+msgstr ""
+
+#: forum/skins/default/templates/logout.html:6
+#: forum/skins/default/templates/logout.html:16
+msgid "Logout"
+msgstr ""
+
+#: forum/skins/default/templates/logout.html:19
+msgid ""
+"As a registered user you can login with your OpenID, log out of the site or "
+"permanently remove your account."
+msgstr ""
+
+#: forum/skins/default/templates/logout.html:20
+msgid "Logout now"
+msgstr ""
+
+#: forum/skins/default/templates/notarobot.html:3
+msgid "Please prove that you are a Human Being"
+msgstr ""
+
+#: forum/skins/default/templates/notarobot.html:10
+msgid "I am a Human Being"
+msgstr ""
+
+#: forum/skins/default/templates/pagesize.html:6
+msgid "posts per page"
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:6
+#: forum/skins/default/templates/paginator.html:7
+msgid "previous"
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:19
+msgid "current page"
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:22
+#: forum/skins/default/templates/paginator.html:29
+msgid "page number "
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:22
+#: forum/skins/default/templates/paginator.html:29
+msgid "number - make blank in english"
+msgstr ""
+
+#: forum/skins/default/templates/paginator.html:33
+msgid "next page"
+msgstr ""
+
+#: forum/skins/default/templates/post_contributor_info.html:9
+#, python-format
+msgid ""
+"\n"
+"                one revision\n"
+"            "
+msgid_plural ""
+"\n"
+"                %(rev_count)s revisions\n"
+"            "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/post_contributor_info.html:24
+msgid "posted"
+msgstr ""
+
+#: forum/skins/default/templates/post_contributor_info.html:45
+msgid "updated"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:6
+#: forum/skins/default/templates/privacy.html:11
+msgid "Privacy policy"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:15
+msgid "general message about privacy"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:18
+msgid "Site Visitors"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:20
+msgid "what technical information is collected about visitors"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:23
+msgid "Personal Information"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:25
+msgid "details on personal information policies"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:28
+msgid "Other Services"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:30
+msgid "details on sharing data with third parties"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:35
+msgid "cookie policy details"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:37
+msgid "Policy Changes"
+msgstr ""
+
+#: forum/skins/default/templates/privacy.html:38
+msgid "how privacy policies can be changed"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:70
+#: forum/skins/default/templates/sidebar/recent_tags.html:9
+#, python-format
+msgid "see questions tagged '%(tagname)s'"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:87
+#, python-format
+msgid ""
+"The question has been closed for the following reason \"%(close_reason)s\" by"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:89
+#, python-format
+msgid "close date %(closed_at)s"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:97
+#, python-format
+msgid ""
+"\n"
+"                    One Answer:\n"
+"                    "
+msgid_plural ""
+"\n"
+"                    %(counter)s Answers:\n"
+"                    "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/question.html:105
+msgid "oldest answers will be shown first"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:105
+msgid "oldest answers"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:107
+msgid "newest answers will be shown first"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:107
+msgid "newest answers"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:109
+msgid "most voted answers will be shown first"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:109
+msgid "popular answers"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:157
+msgid "Your answer"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:159
+msgid "Be the first one to answer this question!"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:165
+msgid "you can answer anonymously and then login"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:169
+msgid "answer your own question only to give an answer"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:171
+msgid "please only give an answer, no discussions"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:207
+msgid "Login/Signup to Post Your Answer"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:210
+msgid "Answer Your Own Question"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:212
+msgid "Answer the question"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:229
+msgid "Question tags"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:239
+msgid "question asked"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:242
+msgid "question was seen"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:242
+msgid "times"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:245
+msgid "last updated"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:250
+msgid "Related questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_edit.html:5
+#: forum/skins/default/templates/question_edit.html:63
+msgid "Edit question"
+msgstr ""
+
+#: forum/skins/default/templates/question_edit_tips.html:4
+msgid "question tips"
+msgstr ""
+
+#: forum/skins/default/templates/question_edit_tips.html:9
+#, python-format
+msgid ""
+"\n"
+"                ask a question relevant to the %(app_title)s community \n"
+"                "
+msgstr ""
+
+#: forum/skins/default/templates/question_edit_tips.html:15
+msgid "please try provide enough details"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:5
+#: forum/skins/default/templates/question_retag.html:56
+msgid "Change tags"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:44
+msgid "up to 5 tags, less than 20 characters each"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:86
+msgid "Why use and modify tags?"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:89
+msgid "tags help us keep Questions organized"
+msgstr ""
+
+#: forum/skins/default/templates/question_retag.html:97
+msgid "tag editors receive special awards from the community"
+msgstr ""
+
+#: forum/skins/default/templates/questions.html:7
+msgid "Questions"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:6
+#: forum/skins/default/templates/reopen.html:16
+msgid "Reopen question"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:19
+msgid "Open the previously closed question"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:22
+msgid "The question was closed for the following reason "
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:22
+msgid "reason - leave blank in english"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:22
+msgid "on "
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:22
+msgid "date closed"
+msgstr ""
+
+#: forum/skins/default/templates/reopen.html:29
+msgid "Reopen this question"
+msgstr ""
+
+#: forum/skins/default/templates/revisions_answer.html:7
+#: forum/skins/default/templates/revisions_answer.html:36
+#: forum/skins/default/templates/revisions_question.html:7
+#: forum/skins/default/templates/revisions_question.html:35
+msgid "Revision history"
+msgstr ""
+
+#: forum/skins/default/templates/revisions_answer.html:48
+#: forum/skins/default/templates/revisions_question.html:47
+msgid "click to hide/show revision"
+msgstr ""
+
+#: forum/skins/default/templates/revisions_answer.html:56
+#: forum/templatetags/node_tags.py:62
+msgid "edit"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:3
+msgid "Subscription"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:8
+msgid "You were automatically subscribed to this question."
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:10
+msgid "You are subscribed to this question."
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:13
+msgid "You are not subscribed to this question."
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:18
+#: forum/views/commands.py:323
+msgid "unsubscribe me"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:20
+#: forum/views/commands.py:323
+msgid "subscribe me"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:24
+#, python-format
+msgid ""
+"\n"
+"            (you can adjust your notification settings on your <a href=\"%"
+"(profile_url)s?sort=email_subscriptions\">profile</a>)\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:29
+msgid "Once you sign in you will be able to subscribe for any updates here"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:4
+#: forum/skins/default/templates/question_list/tag_selector.html:6
+msgid "Interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:10
+#: forum/skins/default/templates/tag_selector.html:27
+#: forum/skins/default/templates/question_list/related_tags.html:9
+#: forum/skins/default/templates/question_list/tag_selector.html:12
+#: forum/skins/default/templates/question_list/tag_selector.html:29
+#, python-format
+msgid "see questions tagged '%(tag_name)s'"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:14
+#: forum/skins/default/templates/question_list/tag_selector.html:16
+#, python-format
+msgid "remove '%(tag_name)s' from the list of interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:20
+#: forum/skins/default/templates/tag_selector.html:37
+#: forum/skins/default/templates/question_list/tag_selector.html:22
+#: forum/skins/default/templates/question_list/tag_selector.html:39
+msgid "Add"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:21
+#: forum/skins/default/templates/question_list/tag_selector.html:23
+msgid "Ignored tags"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:31
+#: forum/skins/default/templates/question_list/tag_selector.html:33
+#, python-format
+msgid "remove '%(tag_name)s' from the list of ignored tags"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:40
+#: forum/skins/default/templates/question_list/tag_selector.html:42
+msgid "keep ignored questions hidden"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:6
+#: forum/skins/default/templates/tags.html:30
+msgid "Tag list"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:32
+msgid "sorted alphabetically"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:32
+msgid "by name"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:33
+msgid "sorted by frequency of tag use"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:33
+msgid "by popularity"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:39
+msgid "All tags matching query"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:39
+msgid "all tags - make this empty in english"
+msgstr ""
+
+#: forum/skins/default/templates/tags.html:42
+msgid "Nothing found"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:5
+#: forum/skins/default/templates/auth/auth_settings.html:7
+msgid "Authentication settings"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:9
+msgid ""
+"These are the external authentication providers currently associated with "
+"your account."
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:12
+msgid "remove"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:17
+msgid ""
+"You currently have no external authentication provider associated with your "
+"account."
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:19
+msgid "Add new provider"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:21
+msgid "This is where you can change your password. Make sure you remember it!"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:24
+msgid ""
+"You can set up a password for your account, so you can login using standard "
+"username and password!"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:31
+msgid "Create password"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:5
+msgid "Connect your OpenID with this site"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:8
+msgid "Connect your OpenID with your account on this site"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:12
+msgid "You are here for the first time with "
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:13
+msgid ""
+"Please create your screen name and save your email address. Saved email "
+"address will let you subscribe for the updates on the most interesting "
+"questions and will be used to create and retrieve your unique avatar image. "
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:15
+msgid "This account already exists, please use another."
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:30
+msgid "Sorry, looks like we have some errors:"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:47
+msgid "Screen name label"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:54
+msgid "Email address label"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:60
+#: forum/skins/default/templates/auth/signup.html:18
+msgid "receive updates motivational blurb"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:64
+#: forum/skins/default/templates/auth/signup.html:22
+msgid "please select one of the options above"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:67
+msgid "Tag filter tool will be your right panel, once you log in."
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:68
+msgid "create account"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:77
+msgid "Existing account"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:78
+msgid "user name"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:79
+msgid "password"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:86
+msgid "Register"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:87
+msgid "Forgot your password?"
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:6
+#: forum/skins/default/templates/auth/temp_login_email.html:6
+msgid "Greetings from the Q&A forum"
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:8
+msgid "To make use of the Forum, please follow the link below:"
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:12
+msgid "Following the link above will help us verify your email address."
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:14
+#: forum/skins/default/templates/auth/temp_login_email.html:14
+msgid ""
+"If you beleive that this message was sent in mistake -\n"
+"    no further action is needed. Just ingore this email, we apologize\n"
+"    for any inconvenience"
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:18
+#: forum/skins/default/templates/auth/temp_login_email.html:18
+#: forum/skins/default/templates/notifications/answeraccepted.html:15
+#: forum/skins/default/templates/notifications/newanswer.html:25
+#: forum/skins/default/templates/notifications/newcomment.html:32
+#: forum/skins/default/templates/notifications/newmember.html:15
+#: forum/skins/default/templates/notifications/newquestion.html:25
+msgid ""
+"Sincerely,<br />\n"
+"    Forum Administrator"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:6
+msgid "Login"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:24
+msgid "User login"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:36
+#: forum/skins/default/templates/auth/signin.html:86
+#: forum/skins/default/templates/auth/signin.html:92
+msgid "Or..."
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:39
+msgid "Click to sign in through any of these services."
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:44
+msgid "Validate my email after I login."
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:94
+msgid "Click"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:94
+msgid "if you're having troubles signing in."
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:98
+msgid "Enter your "
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:154
+msgid "Why use OpenID?"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:157
+msgid "with openid it is easier"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:160
+msgid "reuse openid"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:163
+msgid "openid is widely adopted"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:166
+msgid "openid is supported open standard"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:171
+msgid "Find out more"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:172
+msgid "Get OpenID"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:4
+msgid "Signup"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:8
+msgid "Create login name and password"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:10
+msgid "Traditional signup info"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:31
+msgid "Create Account"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:32
+msgid "or"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:33
+msgid "return to login page"
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_email.html:8
+msgid "You're seeing this because someone requested a temporary login link"
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_email.html:12
+msgid "Following the link above will give you access to your account."
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:5
+msgid "Request temporary login key"
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:7
+msgid "Account: request temporary login key"
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:8
+msgid ""
+"\n"
+"    If you're experiencing problems accessing your account, or if you forgot "
+"your password,\n"
+"    here you can request a temporary login key. Fill out your account email "
+"and we'll send you a temporary access link that\n"
+"    will enable you to access your account. This token is valid only once "
+"and for a limited period of time.\n"
+" "
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:25
+msgid "Send link"
+msgstr ""
+
+#: forum/skins/default/templates/node/accept_button.html:5
+#, python-format
+msgid "%(who)s has selected this answer as the correct answer"
+msgstr ""
+
+#: forum/skins/default/templates/node/accept_button.html:5
+msgid "mark this answer as the accepted answer"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:22
+msgid "I like this comment (click again to cancel)"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:26
+msgid "Edit comment"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:30
+msgid "Delete comment"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:42
+#, python-format
+msgid "showing %(showing)s of %(total)s"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:44
+msgid "show all"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:47
+msgid "add new comment"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:55
+msgid " add comment"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:58
+#, python-format
+msgid ""
+"\n"
+"                have <span class=\"comments-char-left-count\">%(max_length)"
+"s</span> characters left\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:71
+msgid "just now"
+msgstr ""
+
+#: forum/skins/default/templates/node/favorite_mark.html:3
+msgid "mark/unmark this question as favorite (click again to cancel)"
+msgstr ""
+
+#: forum/skins/default/templates/node/vote_buttons.html:3
+msgid "I like this post (click again to cancel)"
+msgstr ""
+
+#: forum/skins/default/templates/node/vote_buttons.html:7
+msgid "current number of votes"
+msgstr ""
+
+#: forum/skins/default/templates/node/vote_buttons.html:10
+msgid "I dont like this post (click again to cancel)"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/answeraccepted.html:6
+#: forum/skins/default/templates/notifications/digest.html:7
+#: forum/skins/default/templates/notifications/newanswer.html:6
+#: forum/skins/default/templates/notifications/newcomment.html:6
+#: forum/skins/default/templates/notifications/newmember.html:6
+#: forum/skins/default/templates/notifications/newquestion.html:6
+msgid "Hello"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/answeraccepted.html:9
+#, python-format
+msgid ""
+"\n"
+"        Just to let you know that %(accepter)s has just accepted %"
+"(answer_author)s's answer on his question\n"
+"        <a href=\"%(app_url)s%(question_url)s\">%(question_title)s</a>:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:9
+#, python-format
+msgid ""
+"\n"
+"    This is the %(digest_type)s activity digest for %(app_title)s\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:15
+#, python-format
+msgid ""
+"\n"
+"            %(nusers_count)s new user%(nusers_count_pluralize)s joined the %"
+"(app_title)s community:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:28
+#, python-format
+msgid ""
+"\n"
+"            %(question_count)s of your subscriptions have updates:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:35
+msgid "On question "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:37
+#, python-format
+msgid ""
+"\n"
+"                    %(answer_count)s new answer%(answer_count_pluralize)s\n"
+"                "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:42
+#, python-format
+msgid ""
+"\n"
+"                    %(comment_count)s new comment%(comment_count_pluralize)"
+"s\n"
+"                "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:46
+msgid "on your own post(s)"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:50
+msgid "an answer was accepted"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:59
+#, python-format
+msgid ""
+"\n"
+"            %(question_count)s new question%(question_count_pluralize)s\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:63
+msgid "matching your interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:65
+msgid "posted :"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:71
+#, python-format
+msgid ""
+"\n"
+"                    Posted by %(author_name)s in %(question_time)s\n"
+"                "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:7
+#, python-format
+msgid ""
+"\n"
+"    Hello, this is a %(site_title)s forum feedback message\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:13
+msgid "Sender"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:15
+#: forum/skins/default/templates/notifications/feedback.html:18
+#: forum/skins/default/templates/users/info.html:93
+msgid "email"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:17
+msgid "anonymous"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:25
+msgid "Message body:"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newanswer.html:9
+#, python-format
+msgid ""
+"\n"
+"        %(author_name)s has just posted a new answer on %(app_title)s to the "
+"question\n"
+"        <a href=\"%(app_url)s%(question_url)s\">%(question_title)s\"</a>:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newanswer.html:20
+#: forum/skins/default/templates/notifications/newcomment.html:28
+#: forum/skins/default/templates/notifications/newquestion.html:20
+msgid ""
+"\n"
+"        Don't forget to come over and cast your vote.\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newcomment.html:9
+#, python-format
+msgid ""
+"\n"
+"            %(author_name)s has just posted a comment on\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newcomment.html:14
+#, python-format
+msgid ""
+"\n"
+"                the answer posted by <a href=\"%(app_url)s%(poster_url)s\">%"
+"(poster_name)s</a> to\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newcomment.html:19
+#, python-format
+msgid ""
+"\n"
+"             the question  <a href=\"%(app_url)s%(question_url)s\">%"
+"(question_title)s</a>\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newmember.html:9
+#, python-format
+msgid ""
+"\n"
+"        %(newmember_name)s has just joined %(app_title)s. You can visit %"
+"(newmember_name)s's profile using the following link: <br />\n"
+"        <a href=\"%(app_url)s%(newmember_url)s\">%(newmember_name)s profile</"
+"a>\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newquestion.html:9
+#, python-format
+msgid ""
+"\n"
+"        %(author_name)s has just posted a new question on %(app_title)s, "
+"with title\n"
+"        <a href=\"%(app_url)s%(question_url)s\">%(question_title)s</a> and "
+"tagged <em>%(question_tags)s</em>:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/base.html:13
+msgid "OSQA administration area"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/base.html:26
+msgid "Administration menu"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:7
+msgid "Dashboard"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:10
+msgid "Welcome to the OSQA administration area."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:17
+msgid "Site statistics"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:21
+#: forum/skins/default/templates/osqaadmin/index.html:26
+msgid "in the last 24 hours"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:31
+msgid "user"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:31
+msgid "joined in the last 24 hours"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:37
+msgid "Site status"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:42
+msgid ""
+"Your site is running in bootstrap mode, click the button bellow to revert to "
+"defaults."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:45
+msgid ""
+"Your site is running in standard mode, click the button bellow to run in "
+"bootstrap mode."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:47
+msgid ""
+"Your site is running with some customized settings, click the buttons bellow "
+"to run with defaults or in bootstrap mode"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:51
+msgid "Are you sure you want to revert to the defaults?"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:51
+msgid "revert to defaults"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:54
+msgid "Are you sure you want to run bootstrap mode?"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:54
+msgid "go bootstrap"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:59
+msgid "Recalculate scores and reputation"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:60
+msgid "This is a heavy operation, are you sure?"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:60
+msgid "Recalculate"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:65
+msgid "Recent activity"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/item.html:12
+msgid "this question has an accepted answer"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/related_tags.html:6
+msgid "Related tags"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:4
+msgid "most recently updated questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:4
+msgid "active"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:5
+msgid "most recently asked questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:5
+msgid "newest"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:6
+msgid "hottest questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:6
+msgid "hottest"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:7
+msgid "most voted questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:7
+msgid "most voted"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:5
+msgid "Found by tags"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:9
+msgid "Search results"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:11
+msgid "Found by title"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:15
+msgid "Unanswered questions"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:17
+#: forum/skins/default/templates/users/subscriptions.html:74
+msgid "All questions"
+msgstr ""
+
+#: forum/skins/default/templates/sidebar/recent_awards.html:4
+msgid "Recent awards"
+msgstr ""
+
+#: forum/skins/default/templates/sidebar/recent_awards.html:15
+msgid "all awards"
+msgstr ""
+
+#: forum/skins/default/templates/sidebar/recent_tags.html:4
+msgid "Recent tags"
+msgstr ""
+
+#: forum/skins/default/templates/sidebar/recent_tags.html:12
+msgid "popular tags"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:6
+msgid "Edit user profile"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:19
+msgid "edit profile"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:31
+msgid "image associated with your email address"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:31
+#, python-format
+msgid "avatar, see %(gravatar_faq_url)s"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:36
+#: forum/skins/default/templates/users/info.html:52
+msgid "Registered user"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:43
+msgid "Screen Name"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:86
+#: forum/skins/default/templates/users/subscriptions.html:116
+msgid "Update"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:22
+#: forum/skins/default/templates/users/signature.html:6
+#: forum/skins/default/templates/users/users.html:26
+msgid "reputation"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:32
+msgid "Moderate this user"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:44
+msgid "update profile"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:56
+msgid "real name"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:61
+msgid "member for"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:66
+msgid "last seen"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:72
+msgid "user website"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:78
+msgid "location"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:86
+msgid "age"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:87
+msgid "age unit"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:100
+msgid "todays unused votes"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:101
+msgid "votes left"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:13
+#, python-format
+msgid ""
+"\n"
+"                <span class=\"count\">1</span> Question\n"
+"                "
+msgid_plural ""
+"\n"
+"                <span class=\"count\">%(counter)s</span> Questions\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:29
+#, python-format
+msgid ""
+"\n"
+"                <span class=\"count\">1</span> Answer\n"
+"                "
+msgid_plural ""
+"\n"
+"                <span class=\"count\">%(counter)s</span> Answers\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:42
+#, python-format
+msgid "the answer has been voted for %(vote_count)s times"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:42
+msgid "this answer has been selected as correct"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:58
+#, python-format
+msgid ""
+"\n"
+"                    <span class=\"count\">1</span> Vote\n"
+"                "
+msgid_plural ""
+"\n"
+"                    <span class=\"count\">%(cnt)s</span> Votes\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:69
+msgid "thumb up"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:70
+msgid "user has voted up this many times"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:74
+msgid "thumb down"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:75
+msgid "user voted down this many times"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:84
+#, python-format
+msgid ""
+"\n"
+"                    <span class=\"count\">1</span> Tag\n"
+"                "
+msgid_plural ""
+"\n"
+"                    <span class=\"count\">%(counter)s</span> Tags\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:97
+#, python-format
+msgid ""
+"see other questions with %(view_user)s's contributions tagged '%(tag_name)s' "
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:112
+#, python-format
+msgid ""
+"\n"
+"            <span class=\"count\">1</span> Badge\n"
+"            "
+msgid_plural ""
+"\n"
+"            <span class=\"count\">%(counter)s</span> Badges\n"
+"            "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/subscriptions.html:8
+msgid "Notifications and subscription settings"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:10
+msgid ""
+"\n"
+"        Here you can decide which types of notifications you wish to "
+"receive, and it's frequency.<br />\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:14
+msgid ""
+"\n"
+"        Currently you have notifications enabled. You can always stop all "
+"notifications without loosing your settings and restart them afterwards.<br /"
+">\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:18
+msgid ""
+"\n"
+"        Currently you have notifications disabled. You can enable them "
+"clicking on the <strong>Start notifications</strong> button bellow.<br />\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:28
+msgid "Notify me when:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:32
+msgid "A new member joins"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:36
+msgid "A new question is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:40
+msgid "A new question matching my interesting tags is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:44
+msgid "There's an update on one of my subscriptions"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:52
+msgid "Auto subscribe me to:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:57
+msgid "Questions I ask"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:60
+msgid "Questions I answer"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:63
+msgid "Questions I comment"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:68
+msgid "Questions I view"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:71
+msgid "All questions matching my interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:82
+msgid "On my subscriptions, notify me when:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:87
+msgid "An answer is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:90
+msgid "A comment on one of my posts is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:95
+msgid "A comment is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:98
+msgid "An answer is accepted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:106
+msgid "More:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:111
+msgid ""
+"Notify me when someone replys to one of my comments on any post using the "
+"<pre>@username</pre> notation"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:118
+msgid "Stop notifications"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:120
+msgid "Start notifications"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:7
+msgid "User profile"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:7
+msgid "overview"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:9
+msgid "recent activity"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:11
+msgid "graph of user reputation"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:12
+msgid "reputation history"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:15 forum/views/users.py:196
+msgid "user vote record"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:15
+msgid "casted votes"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:18
+msgid "questions that user selected as his/her favorite"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:19
+msgid "favorites"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:22
+msgid "email subscription settings"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:23
+msgid "subscriptions"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:6
+#: forum/skins/default/templates/users/users.html:24
+msgid "Users"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:27
+msgid "recent"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:28
+msgid "oldest"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:29
+msgid "by username"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:35
+#, python-format
+msgid "users matching query %(suser)s:"
+msgstr ""
+
+#: forum/skins/default/templates/users/users.html:39
+msgid "Nothing found."
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:168 forum/templatetags/extra_tags.py:195
+msgid "reputation points"
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:248
+msgid "2 days ago"
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:250
+msgid "yesterday"
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:252
+#, python-format
+msgid "%(hr)d hour ago"
+msgid_plural "%(hr)d hours ago"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/templatetags/extra_tags.py:254
+#, python-format
+msgid "%(min)d min ago"
+msgid_plural "%(min)d mins ago"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/templatetags/node_tags.py:58
+msgid "permanent link"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:58
+msgid "answer permanent link"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:64
+msgid "retag"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:68
+msgid "reopen"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:70
+msgid "close"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:73 forum/views/commands.py:124
+#: forum/views/commands.py:136
+msgid "flag"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:79
+msgid ""
+"report as offensive (i.e containing spam, advertising, malicious text, etc.)"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:82
+msgid "delete"
+msgstr ""
+
+#: forum/templatetags/question_list_tags.py:57
+msgid "<strong>Newest</strong> questions are shown first. "
+msgstr ""
+
+#: forum/templatetags/question_list_tags.py:58
+msgid "Questions are sorted by the <strong>time of last update</strong>."
+msgstr ""
+
+#: forum/templatetags/question_list_tags.py:59
+msgid "Questions sorted by <strong>number of responses</strong>."
+msgstr ""
+
+#: forum/templatetags/question_list_tags.py:60
+msgid "Questions are sorted by the <strong>number of votes</strong>."
+msgstr ""
+
+#: forum/templatetags/user_tags.py:58 forum/views/readers.py:293
+#, python-format
+msgid "Revision n. %(rev_number)d"
+msgstr ""
+
+#: forum/utils/forms.py:32
+msgid "this field is required"
+msgstr ""
+
+#: forum/utils/forms.py:47
+msgid "choose a username"
+msgstr ""
+
+#: forum/utils/forms.py:52
+msgid "user name is required"
+msgstr ""
+
+#: forum/utils/forms.py:53
+msgid "sorry, this name is taken, please choose another"
+msgstr ""
+
+#: forum/utils/forms.py:54
+msgid "sorry, this name is not allowed, please choose another"
+msgstr ""
+
+#: forum/utils/forms.py:55
+msgid "sorry, there is no user with this name"
+msgstr ""
+
+#: forum/utils/forms.py:56
+msgid "sorry, we have a serious error - user name is taken by several users"
+msgstr ""
+
+#: forum/utils/forms.py:57
+msgid "user name can only consist of letters, empty space and underscore"
+msgstr ""
+
+#: forum/utils/forms.py:105
+msgid "your email address"
+msgstr ""
+
+#: forum/utils/forms.py:106
+msgid "email address is required"
+msgstr ""
+
+#: forum/utils/forms.py:108
+msgid "this email is already used by someone else, please choose another"
+msgstr ""
+
+#: forum/utils/forms.py:133
+msgid "choose password"
+msgstr ""
+
+#: forum/utils/forms.py:134
+msgid "password is required"
+msgstr ""
+
+#: forum/utils/forms.py:137
+msgid "retype password"
+msgstr ""
+
+#: forum/utils/forms.py:138
+msgid "please, retype your password"
+msgstr ""
+
+#: forum/utils/forms.py:139
+msgid "sorry, entered passwords did not match, please try again"
+msgstr ""
+
+#: forum/views/admin.py:47
+#, python-format
+msgid "'%s' settings saved succesfully"
+msgstr ""
+
+#: forum/views/admin.py:141
+msgid "Bootstrap mode enabled"
+msgstr ""
+
+#: forum/views/admin.py:155
+msgid "All values reverted to defaults"
+msgstr ""
+
+#: forum/views/admin.py:171
+msgid "All values recalculated"
+msgstr ""
+
+#: forum/views/auth.py:103 forum/views/auth.py:112
+msgid ""
+"Sorry, these login credentials belong to anoother user. Plese terminate your "
+"current session and try again."
+msgstr ""
+
+#: forum/views/auth.py:105
+msgid "You are already logged in with that user."
+msgstr ""
+
+#: forum/views/auth.py:110
+msgid "These login credentials are already associated with your account."
+msgstr ""
+
+#: forum/views/auth.py:116
+msgid "The new credentials are now associated with your account"
+msgstr ""
+
+#: forum/views/auth.py:157
+msgid ""
+"Oops, something went wrong in the middle of this process. Please try again."
+msgstr ""
+
+#: forum/views/auth.py:219
+msgid "Temporary login link"
+msgstr ""
+
+#: forum/views/auth.py:224
+msgid "An email has been sent with your temporary login key"
+msgstr ""
+
+#: forum/views/auth.py:239
+msgid ""
+"You are logged in with a temporary access key, please take the time to fix "
+"your issue with authentication."
+msgstr ""
+
+#: forum/views/auth.py:245
+msgid "Email Validation"
+msgstr ""
+
+#: forum/views/auth.py:256
+msgid "Thank you, your email is now validated."
+msgstr ""
+
+#: forum/views/auth.py:280
+msgid "Your password was changed"
+msgstr ""
+
+#: forum/views/auth.py:282
+msgid "New password set"
+msgstr ""
+
+#: forum/views/auth.py:315
+#, python-format
+msgid "You removed the association with %s"
+msgstr ""
+
+#: forum/views/auth.py:353
+#, python-format
+msgid "Welcome back %s, you are now logged in"
+msgstr ""
+
+#: forum/views/commands.py:20
+#, python-format
+msgid ""
+"\n"
+"            Sorry, but you don't have enough reputation points to %(action)s."
+"<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:29
+#, python-format
+msgid ""
+"\n"
+"            Sorry but you cannot %(action)s your own post.<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:38
+#, python-format
+msgid ""
+"\n"
+"            Sorry but anonymous users cannot %(action)s.<br />\n"
+"            Please login or create an account <a href'%(signin_url)s'>here</"
+"a>.\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:47
+#, python-format
+msgid ""
+"\n"
+"            Sorry, but you don't have enough %(action)s left for today..<br /"
+">\n"
+"            The limit is %(limit)s per day..<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:57
+#, python-format
+msgid ""
+"\n"
+"            Sorry, but you cannot %(action)s twice the same post.<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:71 forum/views/commands.py:74
+#: forum/views/commands.py:111
+msgid "vote"
+msgid_plural "votes"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/views/commands.py:89
+#, python-format
+msgid ""
+"Sorry but you cannot cancel a vote after %(ndays)d %(tdays)s from the "
+"original vote"
+msgstr ""
+
+#: forum/views/commands.py:90
+msgid "day"
+msgid_plural "days"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/views/commands.py:110
+#, python-format
+msgid "You have %(nvotes)s %(tvotes)s left today."
+msgstr ""
+
+#: forum/views/commands.py:121 forum/views/commands.py:127
+msgid "flag posts"
+msgstr ""
+
+#: forum/views/commands.py:132
+msgid "flags"
+msgstr ""
+
+#: forum/views/commands.py:149 forum/views/commands.py:155
+msgid "like comments"
+msgstr ""
+
+#: forum/views/commands.py:152
+msgid "like"
+msgstr ""
+
+#: forum/views/commands.py:179 forum/views/commands.py:182
+msgid "delete comments"
+msgstr ""
+
+#: forum/views/commands.py:197
+msgid "mark a question as favorite"
+msgstr ""
+
+#: forum/views/commands.py:221 forum/views/commands.py:233
+msgid "comment"
+msgstr ""
+
+#: forum/views/commands.py:224 forum/views/commands.py:351
+msgid "Invalid request"
+msgstr ""
+
+#: forum/views/commands.py:230
+msgid "edit comments"
+msgstr ""
+
+#: forum/views/commands.py:240
+msgid "Comment is empty"
+msgstr ""
+
+#: forum/views/commands.py:265
+msgid "accept answers"
+msgstr ""
+
+#: forum/views/commands.py:271
+msgid "Sorry but only the question author can accept an answer"
+msgstr ""
+
+#: forum/views/commands.py:295 forum/views/commands.py:298
+msgid "delete posts"
+msgstr ""
+
+#: forum/views/meta.py:43
+#, python-format
+msgid "Feedback message from %(site_name)s"
+msgstr ""
+
+#: forum/views/meta.py:46
+msgid "Thanks for the feedback!"
+msgstr ""
+
+#: forum/views/meta.py:53
+msgid "We look forward to hearing your feedback! Please, give it next time :)"
+msgstr ""
+
+#: forum/views/readers.py:64
+msgid "Open questions without an accepted answer"
+msgstr ""
+
+#: forum/views/readers.py:73
+#, python-format
+msgid "Questions tagged <span class=\"tag\">%(tag)s</span>"
+msgstr ""
+
+#: forum/views/readers.py:131
+#, python-format
+msgid "questions matching '%(keywords)s'"
+msgstr ""
+
+#: forum/views/users.py:152
+msgid "user profile"
+msgstr ""
+
+#: forum/views/users.py:152
+msgid "user profile overview"
+msgstr ""
+
+#: forum/views/users.py:186
+msgid "recent user activity"
+msgstr ""
+
+#: forum/views/users.py:186
+msgid "profile - recent activity"
+msgstr ""
+
+#: forum/views/users.py:196
+msgid "profile - votes"
+msgstr ""
+
+#: forum/views/users.py:203
+msgid "user reputation in the community"
+msgstr ""
+
+#: forum/views/users.py:203
+msgid "profile - user reputation"
+msgstr ""
+
+#: forum/views/users.py:214
+msgid "favorite questions"
+msgstr ""
+
+#: forum/views/users.py:214
+msgid "profile - favorite questions"
+msgstr ""
+
+#: forum/views/users.py:220
+msgid "subscription settings"
+msgstr ""
+
+#: forum/views/users.py:220
+msgid "profile - subscriptions"
+msgstr ""
+
+#: forum/views/users.py:230
+msgid "Notifications are now enabled"
+msgstr ""
+
+#: forum/views/users.py:232
+msgid "Notifications are now disabled"
+msgstr ""
+
+#: forum/views/users.py:239
+msgid "New subscription settings are now saved"
+msgstr ""
+
+#: forum/views/writers.py:68
+msgid "uploading images is limited to users with >60 reputation points"
+msgstr ""
+
+#: forum/views/writers.py:70
+msgid "allowed file types are 'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'"
+msgstr ""
+
+#: forum/views/writers.py:72
+#, python-format
+msgid "maximum upload file size is %sM"
+msgstr ""
+
+#: forum/views/writers.py:74
+#, python-format
+msgid ""
+"Error uploading file. Please contact the site administrator. Thank you. %s"
+msgstr ""
+
+#: forum/views/writers.py:85
+msgid "Initial revision"
+msgstr ""
+
+#: forum/views/writers.py:143
+msgid "Retag"
+msgstr ""
+
+#: forum_modules/books/urls.py:7 forum_modules/books/urls.py:8
+#: forum_modules/books/urls.py:9
+msgid "books/"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:17
+#: forum_modules/default_badges/badges.py:24
+#: forum_modules/default_badges/badges.py:31
+#, python-format
+msgid "Asked a question with %s views"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:39
+#: forum_modules/default_badges/badges.py:53
+#: forum_modules/default_badges/badges.py:67
+#, python-format
+msgid "Answer voted up %s times"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:46
+#: forum_modules/default_badges/badges.py:60
+#: forum_modules/default_badges/badges.py:74
+#, python-format
+msgid "Question voted up %s times"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:82
+#: forum_modules/default_badges/badges.py:89
+#, python-format
+msgid "Question favorited by %s users"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:97
+#, python-format
+msgid "Deleted own post with score of %s or higher"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:108
+#, python-format
+msgid "Deleted own post with score of %s or lower"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:120
+msgid "First flagged post"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:127
+msgid "First down vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:134
+msgid "First retag"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:141
+msgid "First up vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:148
+msgid "First edit"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:155
+msgid "First accepted answer on your own question"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:162
+msgid "Completed all user profile fields"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:169
+msgid "First rollback"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:177
+#, python-format
+msgid "Voted %s times"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:184
+#, python-format
+msgid "Left %s comments"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:192
+#, python-format
+msgid "Answered your own question with at least %s up votes"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:205
+msgid "Strunk & White"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:206
+#, python-format
+msgid "Edited %s entries"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:217
+msgid "Asked first question with at least one up vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:228
+msgid "Answered first question with at least one up vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:260
+#, python-format
+msgid "First answer was accepted with at least %s up votes"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:271
+#, python-format
+msgid "Accepted answer and voted up %s times"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:282
+#, python-format
+msgid ""
+"Answered a question more than %(dif_days)s days later with at least %"
+"(up_votes)s votes"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:295
+#, python-format
+msgid "Created a tag used by %s questions"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:6
+msgid "Popular Question views"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:7
+msgid ""
+"\n"
+"Number of question views required to award a Popular Question badge to the "
+"question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:12
+msgid "Notable Question views"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:13
+msgid ""
+"\n"
+"Number of question views required to award a Notable Question badge to the "
+"question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:18
+msgid "Famous Question views"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:19
+msgid ""
+"\n"
+"Number of question views required to award a Famous Question badge to the "
+"question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:24
+msgid "Nice Answer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:25
+msgid ""
+"\n"
+"Number of up votes required to award a Nice Answer badge to the answer "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:30
+msgid "Nice Question up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:31
+msgid ""
+"\n"
+"Number of up votes required to award a Nice Question badge to the question "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:36
+msgid "Good Answer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:37
+msgid ""
+"\n"
+"Number of up votes required to award a Good Answer badge to the answer "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:42
+msgid "Good Question up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:43
+msgid ""
+"\n"
+"Number of up votes required to award a Good Question badge to the question "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:48
+msgid "Great Answer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:49
+msgid ""
+"\n"
+"Number of up votes required to award a Great Answer badge to the answer "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:54
+msgid "Great Question up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:55
+msgid ""
+"\n"
+"Number of up votes required to award a Great Question badge to the question "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:60
+msgid "Favorite Question favorite count"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:61
+msgid ""
+"\n"
+"How many times a question needs to be favorited by other users to award a "
+"Favorite Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:66
+msgid "Stellar Question favorite count"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:67
+msgid ""
+"\n"
+"How many times a question needs to be favorited by other users to award a "
+"Stellar Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:72
+msgid "Disciplined minimum score"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:73
+msgid ""
+"\n"
+"Minimum score a question needs to have to award the Disciplined badge to an "
+"author of a question who deletes it.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:78
+msgid "Peer Pressure maximum score"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:79
+msgid ""
+"\n"
+"Maximum score a question needs to have to award the Peer Pressure badge to "
+"an author of a question who deletes it.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:84
+msgid "Civic Duty votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:85
+msgid ""
+"\n"
+"Number of votes an user needs to cast to be awarded the Civic Duty badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:90
+msgid "Pundit number of comments"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:91
+msgid ""
+"\n"
+"Number of comments an user needs to post to be awarded the Pundit badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:96
+msgid "Self Learner up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:97
+msgid ""
+"\n"
+"Number of up votes an answer from the question author needs to have for the "
+"author to be awarded the Self Learner badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:102
+msgid "Strunk and White updates"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:103
+msgid ""
+"\n"
+"Number of question or answer updates an user needs to make to be awarded the "
+"Strunk & White badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:108
+msgid "Enlightened up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:109
+msgid ""
+"\n"
+"Number of up votes an accepted answer needs to have for the author to be "
+"awarded the Enlightened badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:114
+msgid "Guru up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:115
+msgid ""
+"\n"
+"Number of up votes an accepted answer needs to have for the author to be "
+"awarded the Guru badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:120
+msgid "Necromancer up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:121
+msgid ""
+"\n"
+"Number of up votes an answer needs to have for the author to be awarded the "
+"Necromancer badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:126
+msgid "Necromancer difference in days"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:127
+msgid ""
+"\n"
+"Difference in days betwen the posted date of a question and an answer for "
+"the answer author to be awarded the Necromancer badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:132
+msgid "Taxonomist usage count"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:133
+msgid ""
+"\n"
+"How many usages a tag needs to have for the tag creator to be awarded the "
+"Taxonomist badge. \n"
+msgstr ""
+
+#: forum_modules/facebookauth/authentication.py:31
+msgid "Sorry, your Facebook session has expired, please try again"
+msgstr ""
+
+#: forum_modules/facebookauth/authentication.py:33
+msgid ""
+"The authentication with Facebook connect failed due to an invalid signature"
+msgstr ""
+
+#: forum_modules/facebookauth/authentication.py:35
+msgid ""
+"The authentication with Facebook connect failed, cannot find authentication "
+"tokens"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:75
+msgid "Please enter valid username and password (both are case-sensitive)."
+msgstr ""
+
+#: forum_modules/localauth/forms.py:79
+msgid "This account is inactive."
+msgstr ""
+
+#: forum_modules/localauth/forms.py:81
+msgid "Login failed."
+msgstr ""
+
+#: forum_modules/localauth/forms.py:85
+msgid "This user is not a valid user"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:88
+msgid "Please enter username and password"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:90
+msgid "Please enter your password"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:92
+msgid "Please enter user name"
+msgstr ""
+
+#: forum_modules/localauth/urls.py:7
+msgid "local/"
+msgstr ""
+
+#: forum_modules/localauth/views.py:33
+msgid "A validation email has been sent to your email address. "
+msgstr ""
+
+#: forum_modules/oauthauth/consumer.py:33
+msgid "Error, the oauth token is not on the server"
+msgstr ""
+
+#: forum_modules/oauthauth/consumer.py:38
+msgid "Something went wrong! Auth tokens do not match"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:40
+msgid "Sorry, but your input is not a valid OpenId"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:92
+msgid "The OpenId authentication request was canceled"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:94
+msgid "The OpenId authentication failed: "
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:96
+msgid "Setup needed"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:98
+msgid "The OpenId authentication failed with an unknown status: "
+msgstr ""
+
+#: forum_modules/openidauth/templates/openidurl.html:7
+msgid "Enter your OpenId Url"
+msgstr ""
+
+#: forum_modules/project_badges/badges.py:9
+#, python-format
+msgid "Got %s upvotes in a question tagged with \"bug\""
+msgstr ""
+
+#: forum_modules/recaptcha/formfield.py:20
+msgid "Invalid captcha"
+msgstr ""
+
+#: forum_modules/sximporter/importer.py:39
+#, python-format
+msgid "Unknown user %(number)d"
+msgstr ""
+
+#: forum_modules/sximporter/urls.py:8
+msgid "sximporter/"
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:7
+msgid "SX Importer"
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:10
+msgid "Welcome to Stack Exchange dump importer."
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:16
+msgid "Your user id in stack exchange"
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:20
+msgid "Merge users with same user name and email"
+msgstr ""
+
+#: locale/phrases.py:1
+msgid "Test Phrase 1"
+msgstr ""
+
+#: locale/phrases.py:2
+msgid "Test Phrase 2"
+msgstr ""
+
+#: locale/phrases.py:3
+msgid "Test Phrase 3"
+msgstr ""
+
+#: locale/phrases.py:4
+msgid "Test Phrase n"
+msgstr ""
diff --git a/forum/modules/template_loader.py/locale/zh_CN/LC_MESSAGES/django.mo b/forum/modules/template_loader.py/locale/zh_CN/LC_MESSAGES/django.mo
new file mode 100644 (file)
index 0000000..66452b7
Binary files /dev/null and b/forum/modules/template_loader.py/locale/zh_CN/LC_MESSAGES/django.mo differ
diff --git a/forum/modules/template_loader.py/locale/zh_CN/LC_MESSAGES/django.po b/forum/modules/template_loader.py/locale/zh_CN/LC_MESSAGES/django.po
new file mode 100644 (file)
index 0000000..fedf00e
--- /dev/null
@@ -0,0 +1,5202 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-04-28 16:53-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"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+
+#: forum/const.py:8
+msgid "duplicate question"
+msgstr "完全重复的问题"
+
+# chinese translation is domain specific
+#: forum/const.py:9
+#, fuzzy
+msgid "question is off-topic or not relevant"
+msgstr "不是编程技术问题"
+
+#: forum/const.py:10
+msgid "too subjective and argumentative"
+msgstr "太主观性、引起争吵的问题"
+
+#: forum/const.py:11
+msgid "is not an answer to the question"
+msgstr "不是一个可以回答的“问题”"
+
+#: forum/const.py:12
+msgid "the question is answered, right answer was accepted"
+msgstr "问题已经解决,已得到正确答案"
+
+#: forum/const.py:13
+msgid "problem is not reproducible or outdated"
+msgstr "已经过时、不可重现的问题"
+
+#: forum/const.py:14
+msgid "question contains offensive inappropriate, or malicious remarks"
+msgstr "恶意言论"
+
+#: forum/const.py:15
+msgid "spam or advertising"
+msgstr "垃圾广告"
+
+#: forum/const.py:71 forum/skins/default/templates/osqaadmin/index.html:21
+msgid "question"
+msgstr "提问"
+
+#: forum/const.py:72 forum/skins/default/templates/book.html:110
+#: forum/skins/default/templates/osqaadmin/index.html:26
+msgid "answer"
+msgstr "回答"
+
+#: forum/const.py:73
+msgid "commented question"
+msgstr "评论问题"
+
+#: forum/const.py:74
+#, fuzzy
+msgid "commented answer"
+msgstr "修改回答"
+
+#: forum/const.py:75
+msgid "edited question"
+msgstr "修改问题"
+
+#: forum/const.py:76
+msgid "edited answer"
+msgstr "修改回答"
+
+#: forum/const.py:77
+msgid "received award"
+msgstr "获奖"
+
+#: forum/const.py:78
+msgid "marked best answer"
+msgstr "标记最佳答案"
+
+#: forum/const.py:79
+msgid "upvoted"
+msgstr "投赞成票"
+
+#: forum/const.py:80
+msgid "downvoted"
+msgstr "投反对票"
+
+#: forum/const.py:81
+#, fuzzy
+msgid "upvote canceled"
+msgstr "投赞成票"
+
+#: forum/const.py:82
+#, fuzzy
+msgid "downvote canceled"
+msgstr "投反对票"
+
+#: forum/const.py:83
+msgid "deleted question"
+msgstr "删除问题"
+
+#: forum/const.py:84
+msgid "deleted answer"
+msgstr "删除回答"
+
+#: forum/const.py:85
+msgid "marked offensive"
+msgstr "标记垃圾帖"
+
+#: forum/const.py:86
+msgid "updated tags"
+msgstr "更新标签"
+
+#: forum/const.py:87
+msgid "selected favorite"
+msgstr "收藏"
+
+#: forum/const.py:88
+msgid "completed user profile"
+msgstr "完成个人所有资料"
+
+#: forum/const.py:89
+msgid "email update sent to user"
+msgstr ""
+
+#: forum/const.py:93
+#, fuzzy
+msgid "question_answered"
+msgstr "提问时间"
+
+#: forum/const.py:94
+#, fuzzy
+msgid "question_commented"
+msgstr "提问时间"
+
+#: forum/const.py:95
+msgid "answer_commented"
+msgstr ""
+
+#: forum/const.py:96
+msgid "answer_accepted"
+msgstr ""
+
+#: forum/const.py:100
+msgid "[closed]"
+msgstr "[已关闭]"
+
+#: forum/const.py:101
+msgid "[deleted]"
+msgstr "[已删除]"
+
+#: forum/const.py:102
+msgid "initial version"
+msgstr "初始版本"
+
+#: forum/const.py:103
+msgid "retagged"
+msgstr "更新了标签"
+
+#: forum/const.py:111
+msgid "Instantly"
+msgstr ""
+
+#: forum/const.py:112
+msgid "Daily"
+msgstr ""
+
+#: forum/const.py:113
+msgid "Weekly"
+msgstr ""
+
+#: forum/const.py:114
+msgid "No notifications"
+msgstr ""
+
+#: forum/feed.py:18
+msgid " - "
+msgstr "-"
+
+#: forum/feed.py:18
+msgid "latest questions"
+msgstr "最新问题"
+
+#: forum/forms.py:21 forum/skins/default/templates/answer_edit_tips.html:35
+#: forum/skins/default/templates/answer_edit_tips.html:39
+#: forum/skins/default/templates/question_edit_tips.html:37
+#: forum/skins/default/templates/question_edit_tips.html:42
+msgid "title"
+msgstr "标题"
+
+#: forum/forms.py:22
+msgid "please enter a descriptive title for your question"
+msgstr ""
+"请输入对问题具有描述性质的标题 - “帮忙!紧急求助!”不是建议的提问方式。"
+
+#: forum/forms.py:27
+msgid "title must be > 10 characters"
+msgstr "标题的长度必须大于10"
+
+#: forum/forms.py:36
+msgid "content"
+msgstr "内容"
+
+#: forum/forms.py:42
+msgid "question content must be > 10 characters"
+msgstr "内容至少要10个字符"
+
+#: forum/forms.py:52 forum/skins/default/templates/header.html:31
+#: forum/skins/default/templates/header.html:56
+msgid "tags"
+msgstr "标签"
+
+#: forum/forms.py:54
+msgid ""
+"Tags are short keywords, with no spaces within. Up to five tags can be used."
+msgstr ""
+
+#: forum/forms.py:61 forum/skins/default/templates/question_retag.html:43
+msgid "tags are required"
+msgstr " 标签不能为空。"
+
+#: forum/forms.py:67
+msgid "please use 5 tags or less"
+msgstr "最多只能有5个标签"
+
+#: forum/forms.py:72
+msgid "tags must be shorter than 20 characters"
+msgstr "每个标签的长度不超过20"
+
+#: forum/forms.py:74
+msgid ""
+"please use following characters in tags: letters 'a-z', numbers, and "
+"characters '.-_#'"
+msgstr "标签请使用英文字母,中文或者数字字符串(. - _ # 也可以)"
+
+# index.html
+#: forum/forms.py:84
+#: forum/skins/default/templates/post_contributor_info.html:7
+#: forum/skins/default/templates/question_summary_list_roll.html:26
+#: forum/skins/default/templates/question_summary_list_roll.html:38
+msgid "community wiki"
+msgstr "社区Wiki"
+
+#: forum/forms.py:85
+msgid ""
+"if you choose community wiki option, the question and answer do not generate "
+"points and name of author will not be shown"
+msgstr "选择社区wiki模式,问答不计算积分,签名也不显示作者信息"
+
+#: forum/forms.py:101
+msgid "update summary:"
+msgstr "更新概要:"
+
+#: forum/forms.py:102
+msgid ""
+"enter a brief summary of your revision (e.g. fixed spelling, grammar, "
+"improved style, this field is optional)"
+msgstr ""
+"输入本次修改的简单概述(如:修改了别字,修正了语法,改进了样式等。非必填"
+"项。)"
+
+#: forum/forms.py:105
+msgid "Automatically accept user's contributions for the email updates"
+msgstr ""
+
+#: forum/forms.py:118
+#, fuzzy
+msgid "Your name:"
+msgstr "用户名"
+
+#: forum/forms.py:119
+#, fuzzy
+msgid "Email (not shared with anyone):"
+msgstr "电子邮件(<i>用于头像显示服务</i>)"
+
+#: forum/forms.py:120
+#, fuzzy
+msgid "Your message:"
+msgstr "Copyright(c)2009.CNPROG.COM"
+
+#: forum/forms.py:202
+msgid "this email does not have to be linked to gravatar"
+msgstr "不会公开,用于头像显示服务"
+
+#: forum/forms.py:204
+#, fuzzy
+msgid "Screen name"
+msgstr "姓名"
+
+#: forum/forms.py:205
+msgid "Real name"
+msgstr "真实姓名"
+
+#: forum/forms.py:206
+msgid "Website"
+msgstr "个人网站"
+
+#: forum/forms.py:207
+msgid "Location"
+msgstr "城市"
+
+#: forum/forms.py:208
+msgid "Date of birth"
+msgstr "生日"
+
+#: forum/forms.py:208
+msgid "will not be shown, used to calculate age, format: YYYY-MM-DD"
+msgstr "不会公开,只会显示您的年龄,格式为:YYYY-MM-DD"
+
+#: forum/forms.py:209 forum/skins/default/templates/account_settings.html:21
+msgid "Profile"
+msgstr "个人简介"
+
+#: forum/forms.py:240 forum/forms.py:241
+msgid "this email has already been registered, please use another one"
+msgstr "该电子邮件已被注册,请选择另一个再试。"
+
+# this is how above two are supposed to be
+#: forum/subscriptions.py:41
+#, fuzzy, python-format
+msgid "New question on %(app_name)s"
+msgstr "查看有关'%(tagname)s'的问题"
+
+#: forum/subscriptions.py:73
+#, fuzzy, python-format
+msgid "New answer to '%(question_title)s'"
+msgstr "回答该问题"
+
+#: forum/subscriptions.py:112
+#, fuzzy, python-format
+msgid "New comment on %(question_title)s"
+msgstr "评论问题"
+
+#: forum/subscriptions.py:136
+#, python-format
+msgid "An answer to '%(question_title)s' was accepted"
+msgstr ""
+
+#: forum/subscriptions.py:156
+#, python-format
+msgid "%(username)s is a new member on %(app_name)s"
+msgstr ""
+
+#: forum/urls.py:44
+#, fuzzy
+msgid "upfiles/"
+msgstr "个人资料"
+
+# footer.html
+#: forum/urls.py:49
+#, fuzzy
+msgid "about/"
+msgstr "关于本站"
+
+#: forum/urls.py:50
+#, fuzzy
+msgid "faq/"
+msgstr "常见问题"
+
+#: forum/urls.py:51
+#, fuzzy
+msgid "privacy/"
+msgstr "隐私政策"
+
+#: forum/urls.py:52
+#, fuzzy
+msgid "logout/"
+msgstr "退出登录"
+
+#: forum/urls.py:53 forum/urls.py:54
+#, fuzzy
+msgid "answers/"
+msgstr "回答"
+
+#: forum/urls.py:53 forum/urls.py:58 forum/urls.py:98
+#: forum/skins/default/templates/users/info.html:44
+#, fuzzy
+msgid "edit/"
+msgstr "编辑"
+
+#: forum/urls.py:54 forum/urls.py:74
+#, fuzzy
+msgid "revisions/"
+msgstr "版本"
+
+#: forum/urls.py:55 forum/urls.py:56 forum/urls.py:57 forum/urls.py:58
+#: forum/urls.py:59 forum/urls.py:60 forum/urls.py:61 forum/urls.py:74
+#, fuzzy
+msgid "questions/"
+msgstr "问题"
+
+#: forum/urls.py:56 forum_modules/books/urls.py:8
+#, fuzzy
+msgid "ask/"
+msgstr "提问于"
+
+#: forum/urls.py:57
+#, fuzzy
+msgid "unanswered/"
+msgstr "回答"
+
+#: forum/urls.py:59
+#, fuzzy
+msgid "close/"
+msgstr "关闭"
+
+#: forum/urls.py:60
+#, fuzzy
+msgid "reopen/"
+msgstr "打开"
+
+#: forum/urls.py:61
+#, fuzzy
+msgid "answer/"
+msgstr "回答"
+
+#: forum/urls.py:63
+#, fuzzy
+msgid "vote/"
+msgstr "票"
+
+#: forum/urls.py:64
+#, fuzzy
+msgid "like_comment/"
+msgstr "评论"
+
+#: forum/urls.py:65
+#, fuzzy
+msgid "comment/"
+msgstr "评论"
+
+#: forum/urls.py:66
+#, fuzzy
+msgid "delete_comment/"
+msgstr "删除任何一个评论"
+
+#: forum/urls.py:67
+#, fuzzy
+msgid "accept_answer/"
+msgstr "回答"
+
+#: forum/urls.py:68
+#, fuzzy
+msgid "mark_favorite/"
+msgstr "收藏"
+
+#: forum/urls.py:69
+msgid "flag/"
+msgstr ""
+
+#: forum/urls.py:70
+msgid "delete/"
+msgstr "删除"
+
+#: forum/urls.py:71
+msgid "subscribe/"
+msgstr ""
+
+#: forum/urls.py:72
+msgid "matching_tags/"
+msgstr ""
+
+#: forum/urls.py:75
+#, fuzzy
+msgid "command/"
+msgstr "评论"
+
+#: forum/urls.py:78
+#, fuzzy
+msgid "question/"
+msgstr "提问"
+
+#: forum/urls.py:79 forum/urls.py:80
+#, fuzzy
+msgid "tags/"
+msgstr "标签"
+
+#: forum/urls.py:82 forum/urls.py:86
+msgid "mark-tag/"
+msgstr ""
+
+#: forum/urls.py:82
+msgid "interesting/"
+msgstr ""
+
+#: forum/urls.py:86
+msgid "ignored/"
+msgstr ""
+
+#: forum/urls.py:90
+msgid "unmark-tag/"
+msgstr ""
+
+#: forum/urls.py:96 forum/urls.py:98 forum/urls.py:100 forum/urls.py:101
+#: forum/urls.py:102 forum/urls.py:103 forum/urls.py:104 forum/urls.py:105
+#: forum/models/user.py:124
+#, fuzzy
+msgid "users/"
+msgstr "用户"
+
+#: forum/urls.py:97
+msgid "moderate-user/"
+msgstr ""
+
+#: forum/urls.py:100
+#, fuzzy
+msgid "subscriptions/"
+msgstr "问题"
+
+#: forum/urls.py:101
+#, fuzzy
+msgid "favorites/"
+msgstr "收藏"
+
+#: forum/urls.py:102
+#, fuzzy
+msgid "reputation/"
+msgstr "积分"
+
+#: forum/urls.py:103
+#, fuzzy
+msgid "votes/"
+msgstr "票"
+
+#: forum/urls.py:104
+#, fuzzy
+msgid "recent/"
+msgstr "最新加入"
+
+#: forum/urls.py:107 forum/urls.py:108
+#, fuzzy
+msgid "badges/"
+msgstr "奖牌榜"
+
+#: forum/urls.py:109
+msgid "messages/"
+msgstr ""
+
+#: forum/urls.py:109
+msgid "markread/"
+msgstr ""
+
+#: forum/urls.py:111
+msgid "nimda/"
+msgstr ""
+
+#: forum/urls.py:113
+msgid "upload/"
+msgstr ""
+
+#: forum/urls.py:114
+#, fuzzy
+msgid "search/"
+msgstr "搜索"
+
+#: forum/urls.py:115
+#, fuzzy
+msgid "feedback/"
+msgstr "问题反馈"
+
+#: forum/urls.py:119 forum/urls.py:120 forum/urls.py:121 forum/urls.py:122
+#: forum/urls.py:123 forum/urls.py:124 forum/urls.py:125 forum/urls.py:126
+#: forum/urls.py:127 forum/urls.py:128 forum/urls.py:129 forum/urls.py:130
+#: forum_modules/localauth/urls.py:7
+#, fuzzy
+msgid "account/"
+msgstr "新帐号"
+
+#: forum/urls.py:119 forum/urls.py:121 forum/urls.py:122
+msgid "signin/"
+msgstr ""
+
+#: forum/urls.py:120
+msgid "signout/"
+msgstr ""
+
+#: forum/urls.py:123
+#, fuzzy
+msgid "done/"
+msgstr "投反对票"
+
+#: forum/urls.py:124 forum_modules/localauth/urls.py:7
+#, fuzzy
+msgid "register/"
+msgstr "确认"
+
+#: forum/urls.py:125
+msgid "validate/"
+msgstr ""
+
+#: forum/urls.py:126 forum/urls.py:127
+msgid "tempsignin/"
+msgstr ""
+
+#: forum/urls.py:128
+#, fuzzy
+msgid "authsettings/"
+msgstr "设置"
+
+#: forum/urls.py:129 forum/urls.py:130
+msgid "providers/"
+msgstr ""
+
+#: forum/urls.py:129
+#, fuzzy
+msgid "remove/"
+msgstr "打开"
+
+#: forum/urls.py:130
+msgid "add/"
+msgstr ""
+
+#: forum/urls.py:133 forum/urls.py:134 forum/urls.py:135 forum/urls.py:136
+#: forum/urls.py:137 forum_modules/sximporter/urls.py:8
+msgid "admin/"
+msgstr ""
+
+#: forum/urls.py:134
+msgid "denormalize/"
+msgstr ""
+
+#: forum/urls.py:135
+msgid "go_bootstrap/"
+msgstr ""
+
+#: forum/urls.py:136
+msgid "go_defaults/"
+msgstr ""
+
+#: forum/authentication/forms.py:21
+#, fuzzy
+msgid "Your account email"
+msgstr "修改电子邮件"
+
+#: forum/authentication/forms.py:23
+msgid "You cannot leave this field blank"
+msgstr ""
+
+#: forum/authentication/forms.py:24 forum/utils/forms.py:107
+msgid "please enter a valid email address"
+msgstr ""
+
+#: forum/authentication/forms.py:32
+msgid "Sorry, but this email is not on our database."
+msgstr ""
+
+#: forum/authentication/forms.py:40
+msgid "okay, let's try!"
+msgstr ""
+
+#: forum/authentication/forms.py:41
+msgid "no OSQA community email please, thanks"
+msgstr ""
+
+#: forum/authentication/forms.py:44
+msgid "please choose one of the options above"
+msgstr ""
+
+#: forum/authentication/forms.py:51
+#, fuzzy
+msgid "Current password"
+msgstr "确认密码"
+
+#: forum/authentication/forms.py:62
+msgid ""
+"Old password is incorrect.                     Please enter the correct "
+"password."
+msgstr ""
+
+#: forum/management/commands/send_email_alerts.py:56
+msgid "Daily digest"
+msgstr ""
+
+#: forum/middleware/anon_user.py:34
+#, python-format
+msgid "First time here? Check out the <a href=\"%s\">FAQ</a>!"
+msgstr ""
+
+#: forum/models/question.py:30
+#, fuzzy
+msgid "[closed] "
+msgstr "[已关闭]"
+
+#: forum/models/question.py:33
+#, fuzzy
+msgid "[deleted] "
+msgstr "[已删除]"
+
+#: forum/models/repute.py:13 forum/skins/default/templates/badges.html:53
+msgid "gold"
+msgstr "金牌"
+
+#: forum/models/repute.py:14 forum/skins/default/templates/badges.html:61
+msgid "silver"
+msgstr "银牌"
+
+#: forum/models/repute.py:15 forum/skins/default/templates/badges.html:68
+msgid "bronze"
+msgstr ""
+
+#: forum/models/tag.py:28
+#, fuzzy
+msgid "interesting"
+msgstr "修改问题"
+
+#: forum/models/tag.py:28
+msgid "ignored"
+msgstr ""
+
+#: forum/models/user.py:255
+#: forum/skins/default/templates/post_contributor_info.html:19
+msgid "asked"
+msgstr "提问于"
+
+#: forum/models/user.py:257
+#: forum/skins/default/templates/post_contributor_info.html:22
+#, fuzzy
+msgid "answered"
+msgstr "回答"
+
+#: forum/models/user.py:259
+#, fuzzy
+msgid "marked an answer"
+msgstr "标记最佳答案"
+
+#: forum/models/user.py:261
+#, fuzzy
+msgid "edited a question"
+msgstr "修改问题"
+
+#: forum/models/user.py:263
+#, fuzzy
+msgid "commented a question"
+msgstr "评论问题"
+
+#: forum/models/user.py:265
+#, fuzzy
+msgid "commented an answer"
+msgstr "修改回答"
+
+#: forum/models/user.py:267
+#, fuzzy
+msgid "edited an answer"
+msgstr "编辑任何问题或答案"
+
+#: forum/models/user.py:269
+#, fuzzy
+msgid "received badge"
+msgstr "获奖"
+
+#: forum/settings/__init__.py:20
+#, fuzzy
+msgid "Badges config"
+msgstr "枚奖牌"
+
+#: forum/settings/__init__.py:20
+msgid "Configure badges on your OSQA site."
+msgstr ""
+
+#: forum/settings/basic.py:9
+#, fuzzy
+msgid "Basic Settings"
+msgstr "设置"
+
+#: forum/settings/basic.py:9
+msgid "The basic settings for your application"
+msgstr ""
+
+#: forum/settings/basic.py:12
+msgid "Application logo"
+msgstr ""
+
+#: forum/settings/basic.py:13
+msgid "Your site main logo."
+msgstr ""
+
+#: forum/settings/basic.py:17
+msgid "Favicon"
+msgstr ""
+
+#: forum/settings/basic.py:18
+msgid "Your site favicon."
+msgstr ""
+
+#: forum/settings/basic.py:22
+#, fuzzy
+msgid "Application title"
+msgstr "【出版日期】"
+
+#: forum/settings/basic.py:23
+msgid "The title of your application that will show in the browsers title bar"
+msgstr ""
+
+#: forum/settings/basic.py:26
+#, fuzzy
+msgid "Application short name"
+msgstr "【出版日期】"
+
+#: forum/settings/basic.py:30
+msgid "Application keywords"
+msgstr ""
+
+#: forum/settings/basic.py:31
+msgid "The meta keywords that will be available through the HTML meta tags."
+msgstr ""
+
+#: forum/settings/basic.py:34
+#, fuzzy
+msgid "Application description"
+msgstr "完全重复的问题"
+
+#: forum/settings/basic.py:35
+msgid "The description of your application"
+msgstr ""
+
+#: forum/settings/basic.py:39
+#, fuzzy
+msgid "Application intro"
+msgstr "【出版日期】"
+
+#: forum/settings/basic.py:40
+msgid ""
+"The introductory page that is visible in the sidebar for anonymous users."
+msgstr ""
+
+#: forum/settings/basic.py:44
+#, fuzzy
+msgid "Copyright notice"
+msgstr "Copyright(c)2009.CNPROG.COM"
+
+#: forum/settings/basic.py:45
+msgid "The copyright notice visible at the footer of your page."
+msgstr ""
+
+#: forum/settings/basic.py:48
+msgid "Maximum length of comment"
+msgstr ""
+
+#: forum/settings/basic.py:49
+msgid "The maximum length a user can enter for a comment."
+msgstr ""
+
+#: forum/settings/email.py:5
+#, fuzzy
+msgid "Email Settings"
+msgstr "设置"
+
+#: forum/settings/email.py:5
+msgid "Email server and other email related settings."
+msgstr ""
+
+#: forum/settings/email.py:8
+msgid "Email Server"
+msgstr ""
+
+#: forum/settings/email.py:9
+msgid "The SMTP server through which your application will be sending emails."
+msgstr ""
+
+#: forum/settings/email.py:13
+msgid "Email Port"
+msgstr ""
+
+#: forum/settings/email.py:14
+msgid ""
+"The port on which your SMTP server is listening to. Usually this is 25, but "
+"can be something else."
+msgstr ""
+
+#: forum/settings/email.py:18
+msgid "Email User"
+msgstr ""
+
+#: forum/settings/email.py:19
+msgid "The username for your SMTP connection."
+msgstr ""
+
+#: forum/settings/email.py:23
+#, fuzzy
+msgid "Email Password"
+msgstr "密码"
+
+#: forum/settings/email.py:24
+msgid "The password for your SMTP connection."
+msgstr ""
+
+#: forum/settings/email.py:29
+#, fuzzy
+msgid "Use TLS"
+msgstr "使用"
+
+#: forum/settings/email.py:30
+msgid "Does your SMTP server usFes TLS for authentication."
+msgstr ""
+
+#: forum/settings/email.py:34
+#, fuzzy
+msgid "Site 'from' email address"
+msgstr "您的电子邮件地址"
+
+#: forum/settings/email.py:35
+msgid ""
+"The address that will show up on the 'from' field on emails sent by your "
+"website."
+msgstr ""
+
+#: forum/settings/email.py:39
+msgid "Email subject prefix"
+msgstr ""
+
+#: forum/settings/email.py:40
+msgid ""
+"Every email sent through your website will have the subject prefixed by this "
+"string. It's usually a good idea to have such a prefix so your users can "
+"easilly set up a filter on their email clients."
+msgstr ""
+
+#: forum/settings/extkeys.py:4
+msgid "External Keys"
+msgstr ""
+
+#: forum/settings/extkeys.py:4
+msgid ""
+"Keys for various external providers that your application may optionally use."
+msgstr ""
+
+#: forum/settings/extkeys.py:7
+msgid "Google sitemap code"
+msgstr ""
+
+#: forum/settings/extkeys.py:8
+msgid ""
+"This is the code you get when you register your site at <a href='https://www."
+"google.com/webmasters/tools/'>Google webmaster central</a>."
+msgstr ""
+
+#: forum/settings/extkeys.py:12
+msgid "Google analytics key"
+msgstr ""
+
+#: forum/settings/extkeys.py:13
+msgid ""
+"Your Google analytics key. You can get one at the <a href='http://www.google."
+"com/analytics/'>Google analytics official website</a>"
+msgstr ""
+
+#: forum/settings/forms.py:40
+#, fuzzy
+msgid "Change this:"
+msgstr "修改问题标签"
+
+#: forum/settings/minrep.py:4
+#, fuzzy
+msgid "Minimum reputation config"
+msgstr "积分"
+
+#: forum/settings/minrep.py:4
+msgid ""
+"Configure the minimum reputation required to perform certain actions on your "
+"site."
+msgstr ""
+
+#: forum/settings/minrep.py:7
+msgid "Minimum reputation to vote up"
+msgstr ""
+
+#: forum/settings/minrep.py:8
+msgid "The minimum reputation an user must have to be allowed to vote up."
+msgstr ""
+
+#: forum/settings/minrep.py:11
+#, fuzzy
+msgid "Minimum reputation to vote down"
+msgstr "用户社区积分"
+
+#: forum/settings/minrep.py:12
+msgid "The minimum reputation an user must have to be allowed to vote down."
+msgstr ""
+
+#: forum/settings/minrep.py:15
+msgid "Minimum reputation to flag a post"
+msgstr ""
+
+#: forum/settings/minrep.py:16
+msgid "The minimum reputation an user must have to be allowed to flag a post."
+msgstr ""
+
+#: forum/settings/minrep.py:19
+#, fuzzy
+msgid "Minimum reputation to comment"
+msgstr "用户社区积分"
+
+#: forum/settings/minrep.py:20
+msgid ""
+"The minimum reputation an user must have to be allowed to comment a post."
+msgstr ""
+
+#: forum/settings/minrep.py:23
+#, fuzzy
+msgid "Minimum reputation to like a comment"
+msgstr "用户社区积分"
+
+#: forum/settings/minrep.py:24
+msgid ""
+"The minimum reputation an user must have to be allowed to \"like\" a comment."
+msgstr ""
+
+#: forum/settings/minrep.py:27
+msgid "Minimum reputation to upload"
+msgstr ""
+
+#: forum/settings/minrep.py:28
+msgid ""
+"The minimum reputation an user must have to be allowed to upload a file."
+msgstr ""
+
+#: forum/settings/minrep.py:31
+msgid "Minimum reputation to close own question"
+msgstr ""
+
+#: forum/settings/minrep.py:32
+msgid ""
+"The minimum reputation an user must have to be allowed to close his own "
+"question."
+msgstr ""
+
+#: forum/settings/minrep.py:35
+msgid "Minimum reputation to reopen own question"
+msgstr ""
+
+#: forum/settings/minrep.py:36
+msgid ""
+"The minimum reputation an user must have to be allowed to reopen his own "
+"question."
+msgstr ""
+
+#: forum/settings/minrep.py:39
+#, fuzzy
+msgid "Minimum reputation to retag others questions"
+msgstr "其他用户的回复和评论"
+
+#: forum/settings/minrep.py:40
+msgid ""
+"The minimum reputation an user must have to be allowed to retag others "
+"questions."
+msgstr ""
+
+#: forum/settings/minrep.py:43
+msgid "Minimum reputation to edit wiki posts"
+msgstr ""
+
+#: forum/settings/minrep.py:44
+msgid ""
+"The minimum reputation an user must have to be allowed to edit community "
+"wiki posts."
+msgstr ""
+
+#: forum/settings/minrep.py:47
+msgid "Minimum reputation to edit others posts"
+msgstr ""
+
+#: forum/settings/minrep.py:48
+msgid ""
+"The minimum reputation an user must have to be allowed to edit others posts."
+msgstr ""
+
+#: forum/settings/minrep.py:51
+msgid "Minimum reputation to close others posts"
+msgstr ""
+
+#: forum/settings/minrep.py:52
+msgid ""
+"The minimum reputation an user must have to be allowed to close others posts."
+msgstr ""
+
+#: forum/settings/minrep.py:55
+#, fuzzy
+msgid "Minimum reputation to delete comments"
+msgstr "用户社区积分"
+
+#: forum/settings/minrep.py:56
+msgid ""
+"The minimum reputation an user must have to be allowed to delete comments."
+msgstr ""
+
+#: forum/settings/minrep.py:59
+msgid "Minimum reputation to view offensive flags"
+msgstr ""
+
+#: forum/settings/minrep.py:60
+msgid "The minimum reputation an user must have to view offensive flags."
+msgstr ""
+
+#: forum/settings/repgain.py:4
+msgid "Reputation gains and losses config"
+msgstr ""
+
+#: forum/settings/repgain.py:4
+msgid ""
+"Configure the reputation points a user may gain or lose upon certain actions."
+msgstr ""
+
+#: forum/settings/repgain.py:7
+#, fuzzy
+msgid "Initial reputation"
+msgstr "积分"
+
+#: forum/settings/repgain.py:8
+msgid "The initial reputation an user gets when he first signs in."
+msgstr ""
+
+#: forum/settings/repgain.py:12
+msgid "Maximum reputation a user can gain in one day for being upvoted."
+msgstr ""
+
+#: forum/settings/repgain.py:15
+msgid "Rep gain by upvoted"
+msgstr ""
+
+#: forum/settings/repgain.py:16
+msgid "Reputation a user gains for having one of his posts up voted."
+msgstr ""
+
+#: forum/settings/repgain.py:19
+msgid "Rep lost bu upvote canceled"
+msgstr ""
+
+#: forum/settings/repgain.py:20
+msgid ""
+"Reputation a user loses for having one of the upvotes on his posts canceled."
+msgstr ""
+
+#: forum/settings/repgain.py:23
+#, fuzzy
+msgid "Rep lost by downvoted"
+msgstr "投反对票"
+
+#: forum/settings/repgain.py:24
+msgid "Reputation a user loses for having one of his posts down voted."
+msgstr ""
+
+#: forum/settings/repgain.py:27
+msgid "Rep lost by downvoting"
+msgstr ""
+
+#: forum/settings/repgain.py:28
+msgid "Reputation a user loses for down voting a post."
+msgstr ""
+
+#: forum/settings/repgain.py:31
+msgid "Rep gain by downvote canceled"
+msgstr ""
+
+#: forum/settings/repgain.py:32
+msgid ""
+"Reputation a user gains for having one of the downvotes on his posts "
+"canceled."
+msgstr ""
+
+#: forum/settings/repgain.py:35
+msgid "Rep gain by canceling downvote"
+msgstr ""
+
+#: forum/settings/repgain.py:36
+msgid "Reputation a user gains for canceling a downvote."
+msgstr ""
+
+#: forum/settings/repgain.py:39
+#, fuzzy
+msgid "Rep gain by accepted answer"
+msgstr "修改回答"
+
+#: forum/settings/repgain.py:40
+msgid "Reputation a user gains for having one of his answers accepted."
+msgstr ""
+
+#: forum/settings/repgain.py:43
+msgid "Rep lost by accepted canceled"
+msgstr ""
+
+#: forum/settings/repgain.py:44
+msgid ""
+"Reputation a user loses for having one of his accepted answers canceled."
+msgstr ""
+
+#: forum/settings/repgain.py:47
+msgid "Rep gain by accepting answer"
+msgstr ""
+
+#: forum/settings/repgain.py:48
+msgid ""
+"Reputation a user gains for accepting an answer to one of his questions."
+msgstr ""
+
+#: forum/settings/repgain.py:51
+msgid "Rep lost by canceling accepted"
+msgstr ""
+
+#: forum/settings/repgain.py:52
+msgid "Reputation a user loses by canceling an accepted answer."
+msgstr ""
+
+#: forum/settings/repgain.py:55
+msgid "Rep lost by post flagged"
+msgstr ""
+
+#: forum/settings/repgain.py:56
+msgid "Reputation a user loses by having one of his posts flagged."
+msgstr ""
+
+#: forum/settings/repgain.py:59
+msgid "Rep lost by post flagged and hidden"
+msgstr ""
+
+#: forum/settings/repgain.py:60
+msgid ""
+"Reputation a user loses by having the last revision of one of his posts "
+"flagged the enough number of times to hide the post."
+msgstr ""
+
+#: forum/settings/repgain.py:63
+msgid "Rep lost by post flagged and deleted"
+msgstr ""
+
+#: forum/settings/repgain.py:64
+msgid ""
+"Reputation a user loses by having the last revision of one of his posts "
+"flagged the enough number of times to delete the post."
+msgstr ""
+
+#: forum/settings/upload.py:5
+msgid "File upload settings"
+msgstr ""
+
+#: forum/settings/upload.py:5
+msgid "File uploads related settings."
+msgstr ""
+
+#: forum/settings/upload.py:8
+msgid "Uploaded files folder"
+msgstr ""
+
+#: forum/settings/upload.py:9
+msgid ""
+"The filesystem path where uploaded files will be stored. Please note that "
+"this folder must exist."
+msgstr ""
+
+#: forum/settings/upload.py:12
+msgid "Uploaded files alias"
+msgstr ""
+
+#: forum/settings/upload.py:13
+msgid ""
+"The url alias for uploaded files. Notice that if you change this setting, "
+"you'll need to restart your site."
+msgstr ""
+
+#: forum/settings/upload.py:16
+msgid "Max file size"
+msgstr ""
+
+#: forum/settings/upload.py:17
+#, fuzzy
+msgid "The maximum allowed file size for uploads in mb."
+msgstr "只允许上传%sK大小的文件!"
+
+#: forum/settings/voting.py:4
+msgid "Voting rules"
+msgstr ""
+
+#: forum/settings/voting.py:4
+msgid "Configure the voting rules on your site."
+msgstr ""
+
+#: forum/settings/voting.py:7
+msgid "Maximum votes per day"
+msgstr ""
+
+#: forum/settings/voting.py:8
+msgid "The maximum number of votes an user can cast per day."
+msgstr ""
+
+#: forum/settings/voting.py:11
+msgid "Start warning about votes left"
+msgstr ""
+
+#: forum/settings/voting.py:12
+msgid "From how many votes left should an user start to be warned about it."
+msgstr ""
+
+#: forum/settings/voting.py:15
+msgid "Maximum flags per day"
+msgstr ""
+
+#: forum/settings/voting.py:16
+msgid "The maximum number of times an can flag a post per day."
+msgstr ""
+
+#: forum/settings/voting.py:19
+msgid "Flag count to hide post"
+msgstr ""
+
+#: forum/settings/voting.py:20
+msgid ""
+"How many times a post needs to be flagged to be hidden from the main page."
+msgstr ""
+
+#: forum/settings/voting.py:23
+#, fuzzy
+msgid "Flag count to delete post"
+msgstr "删除帐号"
+
+#: forum/settings/voting.py:24
+msgid "How many times a post needs to be flagged to be deleted."
+msgstr ""
+
+#: forum/settings/voting.py:27
+#, fuzzy
+msgid "Days to cancel a vote"
+msgstr "撤销投票"
+
+#: forum/settings/voting.py:28
+msgid "How many days an user can cancel a vote after he originaly casted it."
+msgstr ""
+
+#: forum/skins/default/templates/404.html:24
+msgid "Sorry, could not find the page you requested."
+msgstr "对不起,没有找到您请求的页面!"
+
+#: forum/skins/default/templates/404.html:26
+msgid "This might have happened for the following reasons:"
+msgstr "有可能是以下原因导致:"
+
+#: forum/skins/default/templates/404.html:28
+msgid "this question or answer has been deleted;"
+msgstr "你正在查看的问题或者回答已经被删除;"
+
+#: forum/skins/default/templates/404.html:29
+msgid "url has error - please check it;"
+msgstr "请求的地址有误 - 请核实原始URL地址;"
+
+#: forum/skins/default/templates/404.html:30
+msgid ""
+"the page you tried to visit is protected or you don't have sufficient "
+"points, see"
+msgstr "访问的页面被保护或你的积分不够,参见"
+
+#: forum/skins/default/templates/404.html:31
+msgid "if you believe this error 404 should not have occured, please"
+msgstr "如果你确信不该出现404错误,请"
+
+#: forum/skins/default/templates/404.html:32
+msgid "report this problem"
+msgstr "报告这个问题"
+
+#: forum/skins/default/templates/404.html:41
+#: forum/skins/default/templates/500.html:27
+msgid "back to previous page"
+msgstr "返回前页"
+
+#: forum/skins/default/templates/404.html:42
+msgid "see all questions"
+msgstr "查看最新问题"
+
+#: forum/skins/default/templates/404.html:43
+msgid "see all tags"
+msgstr "查看标签列表"
+
+#: forum/skins/default/templates/500.html:22
+msgid "sorry, system error"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:24
+msgid "system error log is recorded, error will be fixed as soon as possible"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:25
+msgid "please report the error to the site administrators if you wish"
+msgstr ""
+
+#: forum/skins/default/templates/500.html:28
+#, fuzzy
+msgid "see latest questions"
+msgstr "最新问题"
+
+#: forum/skins/default/templates/500.html:29
+#, fuzzy
+msgid "see tags"
+msgstr "标记垃圾帖"
+
+#: forum/skins/default/templates/_question_list.html:12
+#: forum/skins/default/templates/book.html:105
+#: forum/skins/default/templates/question_summary_list_roll.html:14
+#: forum/skins/default/templates/question_list/item.html:10
+#: forum/views/commands.py:82
+msgid "votes"
+msgstr "票"
+
+#: forum/skins/default/templates/_question_list.html:14
+#, fuzzy
+msgid "this answer has been accepted to be correct"
+msgstr "有答案已被接受为正确答案"
+
+#: forum/skins/default/templates/_question_list.html:16
+#: forum/skins/default/templates/question_summary_list_roll.html:13
+#: forum/skins/default/templates/question_list/item.html:14
+msgid "answers"
+msgstr "回答"
+
+#: forum/skins/default/templates/_question_list.html:20
+#: forum/skins/default/templates/book.html:115
+#: forum/skins/default/templates/question_summary_list_roll.html:15
+#: forum/skins/default/templates/question_list/item.html:18
+msgid "views"
+msgstr "浏览"
+
+# must have extra space after in english
+#: forum/skins/default/templates/_question_list.html:34
+#: forum/skins/default/templates/question.html:234
+#: forum/skins/default/templates/question_summary_list_roll.html:52
+#: forum/skins/default/templates/tags.html:49
+#: forum/skins/default/templates/question_list/item.html:29
+msgid "see questions tagged"
+msgstr "查看有关"
+
+# book.html line 123 must be empty in english
+#: forum/skins/default/templates/_question_list.html:34
+#: forum/skins/default/templates/book.html:125
+#: forum/skins/default/templates/question.html:234
+#: forum/skins/default/templates/question_summary_list_roll.html:52
+#: forum/skins/default/templates/tags.html:49
+#: forum/skins/default/templates/question_list/item.html:29
+msgid "using tags"
+msgstr "的问题"
+
+# footer.html
+#: forum/skins/default/templates/about.html:5
+#: forum/skins/default/templates/about.html:9
+#, fuzzy
+msgid "About"
+msgstr "关于本站"
+
+#: forum/skins/default/templates/account_settings.html:4
+msgid "Account functions"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:29
+#: forum/skins/default/templates/auth/auth_settings.html:31
+msgid "Change password"
+msgstr "修改密码"
+
+#: forum/skins/default/templates/account_settings.html:30
+msgid "Give your  account a new password."
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:32
+msgid "Change email "
+msgstr "更换电子邮件"
+
+#: forum/skins/default/templates/account_settings.html:33
+msgid "Add or update the email address associated with your account."
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:35
+msgid "Change OpenID"
+msgstr "更换OpenID地址"
+
+#: forum/skins/default/templates/account_settings.html:36
+msgid "Change openid associated to your account"
+msgstr ""
+
+#: forum/skins/default/templates/account_settings.html:39
+msgid "Delete account"
+msgstr "删除帐号"
+
+#: forum/skins/default/templates/account_settings.html:40
+msgid "Erase your username and all your data from website"
+msgstr ""
+
+#: forum/skins/default/templates/answer_edit.html:5
+#: forum/skins/default/templates/answer_edit.html:39
+msgid "Edit answer"
+msgstr "修改回答"
+
+#: forum/skins/default/templates/answer_edit.html:18
+#: forum/skins/default/templates/answer_edit.html:21
+#: forum/skins/default/templates/ask.html:19
+#: forum/skins/default/templates/ask.html:22
+#: forum/skins/default/templates/question_edit.html:19
+#: forum/skins/default/templates/question_edit.html:22
+msgid "hide preview"
+msgstr "禁用预览"
+
+#: forum/skins/default/templates/answer_edit.html:21
+#: forum/skins/default/templates/ask.html:22
+#: forum/skins/default/templates/question_edit.html:22
+msgid "show preview"
+msgstr "启用预览"
+
+#: forum/skins/default/templates/answer_edit.html:39
+#: forum/skins/default/templates/question_edit.html:63
+#: forum/skins/default/templates/question_retag.html:56
+#: forum/skins/default/templates/revisions_answer.html:36
+#: forum/skins/default/templates/revisions_question.html:35
+msgid "back"
+msgstr "返回"
+
+#: forum/skins/default/templates/answer_edit.html:44
+#: forum/skins/default/templates/question_edit.html:68
+#: forum/skins/default/templates/revisions_answer.html:50
+#: forum/skins/default/templates/revisions_question.html:49
+msgid "revision"
+msgstr "版本"
+
+#: forum/skins/default/templates/answer_edit.html:47
+#: forum/skins/default/templates/question_edit.html:72
+msgid "select revision"
+msgstr "选择版本"
+
+#: forum/skins/default/templates/answer_edit.html:54
+#: forum/skins/default/templates/ask.html:93
+#: forum/skins/default/templates/question.html:184
+#: forum/skins/default/templates/question_edit.html:89
+msgid "Toggle the real time Markdown editor preview"
+msgstr "打开或者关闭Markdown编辑器的实时预览"
+
+#: forum/skins/default/templates/answer_edit.html:54
+#: forum/skins/default/templates/ask.html:93
+#: forum/skins/default/templates/question.html:185
+#: forum/skins/default/templates/question_edit.html:89
+msgid "toggle preview"
+msgstr "预览开关"
+
+# synonym of above in Edit question
+#: forum/skins/default/templates/answer_edit.html:63
+#: forum/skins/default/templates/question_edit.html:115
+#: forum/skins/default/templates/question_retag.html:77
+msgid "Save edit"
+msgstr "现在修改"
+
+#: forum/skins/default/templates/answer_edit.html:64
+#: forum/skins/default/templates/close.html:29
+#: forum/skins/default/templates/feedback.html:50
+#: forum/skins/default/templates/question_edit.html:116
+#: forum/skins/default/templates/question_retag.html:78
+#: forum/skins/default/templates/reopen.html:30
+#: forum/skins/default/templates/users/edit.html:87
+msgid "Cancel"
+msgstr "取消"
+
+#: forum/skins/default/templates/answer_edit_tips.html:4
+msgid "answer tips"
+msgstr "受欢迎的提问"
+
+#: forum/skins/default/templates/answer_edit_tips.html:7
+msgid "please make your answer relevant to this community"
+msgstr "您的问题与编程相关吗?"
+
+#: forum/skins/default/templates/answer_edit_tips.html:10
+msgid "try to give an answer, rather than engage into a discussion"
+msgstr "建议您提的问题是可以被答复的,而不仅仅是可以讨论。"
+
+#: forum/skins/default/templates/answer_edit_tips.html:13
+#, fuzzy
+msgid "please try to provide details"
+msgstr "请详细描述您的问题。"
+
+#: forum/skins/default/templates/answer_edit_tips.html:16
+#: forum/skins/default/templates/question_edit_tips.html:18
+msgid "be clear and concise"
+msgstr "我们推荐您使用中文描述问题,这样可以得到更多的答复机会。"
+
+#: forum/skins/default/templates/answer_edit_tips.html:20
+#: forum/skins/default/templates/question_edit_tips.html:22
+msgid "see frequently asked questions"
+msgstr "查看常见问题"
+
+#: forum/skins/default/templates/answer_edit_tips.html:26
+#: forum/skins/default/templates/question_edit_tips.html:28
+msgid "Markdown tips"
+msgstr "Markdown快速参考"
+
+#: forum/skins/default/templates/answer_edit_tips.html:29
+#: forum/skins/default/templates/question_edit_tips.html:31
+#, fuzzy
+msgid "*italic* or __italic__"
+msgstr "*斜体* 或者 _斜体_"
+
+#: forum/skins/default/templates/answer_edit_tips.html:32
+#: forum/skins/default/templates/question_edit_tips.html:34
+msgid "**bold** or __bold__"
+msgstr "**加粗** 或者 __加粗__ "
+
+#: forum/skins/default/templates/answer_edit_tips.html:35
+#: forum/skins/default/templates/question_edit_tips.html:37
+msgid "link"
+msgstr "链接"
+
+#: forum/skins/default/templates/answer_edit_tips.html:35
+#: forum/skins/default/templates/answer_edit_tips.html:39
+#: forum/skins/default/templates/question_edit_tips.html:37
+#: forum/skins/default/templates/question_edit_tips.html:42
+msgid "text"
+msgstr "文本"
+
+#: forum/skins/default/templates/answer_edit_tips.html:39
+#: forum/skins/default/templates/question_edit_tips.html:42
+msgid "image"
+msgstr "图片"
+
+#: forum/skins/default/templates/answer_edit_tips.html:43
+#: forum/skins/default/templates/question_edit_tips.html:46
+msgid "numbered list:"
+msgstr "列表:"
+
+#: forum/skins/default/templates/answer_edit_tips.html:48
+#: forum/skins/default/templates/question_edit_tips.html:51
+msgid "basic HTML tags are also supported"
+msgstr "基本的HTML标签也是支持的"
+
+#: forum/skins/default/templates/answer_edit_tips.html:52
+#: forum/skins/default/templates/question_edit_tips.html:55
+msgid "learn more about Markdown"
+msgstr "有关Markdown详细说明"
+
+#: forum/skins/default/templates/ask.html:5
+#: forum/skins/default/templates/ask.html:57
+msgid "Ask a question"
+msgstr "我要提问"
+
+#: forum/skins/default/templates/ask.html:64
+#, fuzzy
+msgid "login to post question info"
+msgstr "问题按<strong>提问时间</strong>显示排序。新加入的问题将显示在最前面。"
+
+#: forum/skins/default/templates/ask.html:70
+#, python-format
+msgid ""
+"must have valid %(email)s to post, \n"
+"                            see %(email_validation_faq_url)s\n"
+"                            "
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:108
+msgid "(required)"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:115
+msgid "Login/signup to post your question"
+msgstr ""
+
+#: forum/skins/default/templates/ask.html:117
+msgid "Ask your question"
+msgstr "现在提问"
+
+#: forum/skins/default/templates/badge.html:6
+#: forum/skins/default/templates/badge.html:17
+msgid "Badge"
+msgstr "奖牌"
+
+#: forum/skins/default/templates/badge.html:26
+msgid "The users have been awarded with badges:"
+msgstr "用户已被授予该奖牌:"
+
+#: forum/skins/default/templates/badges.html:6
+#, fuzzy
+msgid "Badges summary"
+msgstr "奖牌列表"
+
+#: forum/skins/default/templates/badges.html:17
+msgid "Badges"
+msgstr "枚奖牌"
+
+#: forum/skins/default/templates/badges.html:21
+msgid "Community gives you awards for your questions, answers and votes."
+msgstr ""
+"提出问题,给予回答,投出你的票 - CNProg 会针对你在社区的表现,授予你各类奖"
+"牌。"
+
+#: forum/skins/default/templates/badges.html:22
+#, fuzzy, python-format
+msgid ""
+"Below is the list of available badges and number \n"
+"    of times each type of badge has been awarded. Give us feedback at %"
+"(feedback_faq_url)s.\n"
+"    "
+msgstr "这里列出社区所有的奖牌,以及到目前为此,每个奖牌被授予的用户人数。"
+
+#: forum/skins/default/templates/badges.html:50
+msgid "Community badges"
+msgstr "社区奖牌"
+
+#: forum/skins/default/templates/badges.html:56
+msgid "gold badge description"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:64
+msgid "silver badge description"
+msgstr ""
+
+#: forum/skins/default/templates/badges.html:67
+msgid "bronze badge: often given as a special honor"
+msgstr "铜牌:时常授予之特殊荣誉"
+
+#: forum/skins/default/templates/badges.html:71
+#, fuzzy
+msgid "bronze badge description"
+msgstr "答读者问"
+
+# templates/book.html 78
+#: forum/skins/default/templates/book.html:7
+msgid "reading channel"
+msgstr "读书频道"
+
+#: forum/skins/default/templates/book.html:26
+msgid "[author]"
+msgstr "【作者】"
+
+#: forum/skins/default/templates/book.html:30
+msgid "[publisher]"
+msgstr "【出版社】"
+
+#: forum/skins/default/templates/book.html:34
+msgid "[publication date]"
+msgstr "【出版日期】"
+
+#: forum/skins/default/templates/book.html:38
+msgid "[price]"
+msgstr "【价格】"
+
+#: forum/skins/default/templates/book.html:39
+msgid "currency unit"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:42
+msgid "[pages]"
+msgstr "【页数】"
+
+#: forum/skins/default/templates/book.html:43
+msgid "pages abbreviation"
+msgstr ""
+
+#: forum/skins/default/templates/book.html:46
+msgid "[tags]"
+msgstr "【标签】"
+
+#: forum/skins/default/templates/book.html:56
+msgid "author blog"
+msgstr "作者博客"
+
+#: forum/skins/default/templates/book.html:62
+msgid "book directory"
+msgstr "书籍目录"
+
+#: forum/skins/default/templates/book.html:66
+msgid "buy online"
+msgstr "网上购买"
+
+#: forum/skins/default/templates/book.html:79
+msgid "reader questions"
+msgstr "答读者问"
+
+#: forum/skins/default/templates/book.html:82
+msgid "ask the author"
+msgstr "向作者提问"
+
+#: forum/skins/default/templates/book.html:88
+#: forum/skins/default/templates/book.html:93
+msgid "this question was selected as favorite"
+msgstr "这个问题被"
+
+#: forum/skins/default/templates/book.html:88
+#: forum/skins/default/templates/book.html:93
+msgid "number of times"
+msgstr "位用户收藏"
+
+#: forum/skins/default/templates/book.html:108
+msgid "the answer has been accepted to be correct"
+msgstr "有答案已被接受为正确答案"
+
+#: forum/skins/default/templates/book.html:147
+msgid "subscribe to book RSS feed"
+msgstr "RSS订阅该图书最新问题"
+
+#: forum/skins/default/templates/book.html:147
+msgid "subscribe to the questions feed"
+msgstr "订阅最>新问题"
+
+# close.html
+#: forum/skins/default/templates/close.html:6
+#: forum/skins/default/templates/close.html:16
+msgid "Close question"
+msgstr "关闭问题"
+
+#: forum/skins/default/templates/close.html:19
+msgid "Close the question"
+msgstr "由于以下原因,你要关闭这个问题"
+
+#: forum/skins/default/templates/close.html:25
+msgid "Reasons"
+msgstr "原因"
+
+#: forum/skins/default/templates/close.html:28
+msgid "OK to close"
+msgstr "确定关闭"
+
+#: forum/skins/default/templates/email_base.html:31
+#, fuzzy
+msgid "home"
+msgstr "首页"
+
+#: forum/skins/default/templates/faq.html:11
+msgid "Frequently Asked Questions "
+msgstr "常见问题"
+
+#: forum/skins/default/templates/faq.html:16
+msgid "What kinds of questions can I ask here?"
+msgstr "我可以在这里提问什么样的问题?"
+
+#: forum/skins/default/templates/faq.html:17
+#, fuzzy
+msgid ""
+"Most importantly - questions should be <strong>relevant</strong> to this "
+"community."
+msgstr "毫无疑问,首先必须是<span class=\"yellowbg\">技术编程问题!</span>"
+
+#: forum/skins/default/templates/faq.html:18
+msgid ""
+"Before asking the question - please make sure to use search to see whether "
+"your question has alredy been answered."
+msgstr ""
+"提问之前,充分利用系统的自动查找、标签和搜索,看看是否已经有一样的问题并有了"
+"答案。"
+
+#: forum/skins/default/templates/faq.html:21
+msgid "What questions should I avoid asking?"
+msgstr "什么样的问题我不该在这里提问?"
+
+#: forum/skins/default/templates/faq.html:22
+msgid ""
+"Please avoid asking questions that are not relevant to this community, too "
+"subjective and argumentative."
+msgstr ""
+"<span class=\"yellowbg\">与程序员或技术无关的,引起争吵或太过于主观性等违背社"
+"区宗旨的内容。</span>本站建立是为了帮助大众程序员解决实际技术问题,我们需要实"
+"际的问题!"
+
+#: forum/skins/default/templates/faq.html:27
+msgid "What should I avoid in my answers?"
+msgstr "什么样的回答是不受欢迎的?"
+
+#: forum/skins/default/templates/faq.html:28
+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>功能来讨论你的意见和想法。"
+
+#: forum/skins/default/templates/faq.html:32
+msgid "Who moderates this community?"
+msgstr "谁是社区的管理员?"
+
+#: forum/skins/default/templates/faq.html:33
+msgid "The short answer is: <strong>you</strong>."
+msgstr "答案是:<span class=\"yellowbg\">每个用户。</span>"
+
+#: forum/skins/default/templates/faq.html:34
+msgid "This website is moderated by the users."
+msgstr "社区没有严格意义上的管理员身份"
+
+#: forum/skins/default/templates/faq.html:35
+msgid ""
+"The reputation system allows users earn the authorization to perform a "
+"variety of moderation tasks."
+msgstr ""
+"通过积分运作,<span class=\"yellowbg\">每个用户都有权限创建标签,进行对所有问"
+"题、回答的投票、编辑、关闭等操作。</span>"
+
+#: forum/skins/default/templates/faq.html:40
+msgid "How does reputation system work?"
+msgstr "什么是社区积分?"
+
+#: forum/skins/default/templates/faq.html:41
+#, fuzzy
+msgid "Rep system summary"
+msgstr "更新概要:"
+
+#: forum/skins/default/templates/faq.html:42
+msgid ""
+"For example, if you ask an interesting question or give a helpful answer, "
+"your input will be upvoted. On the other hand if the answer is misleading - "
+"it will be downvoted. Each vote in favor will generate <strong>10</strong> "
+"points, each vote against will subtract <strong>2</strong> points. There is "
+"a limit of <strong>200</strong> points that can be accumulated per question "
+"or answer. The table below explains reputation point requirements for each "
+"type of moderation task."
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:53
+#: forum/skins/default/templates/users/votes.html:15
+#: forum/views/commands.py:77
+msgid "upvote"
+msgstr "投赞成票"
+
+#: forum/skins/default/templates/faq.html:57
+#, fuzzy
+msgid "use tags"
+msgstr "标记垃圾帖"
+
+# todo - check if it's indeed plural
+#: forum/skins/default/templates/faq.html:62
+msgid "add comments"
+msgstr "添加评论"
+
+#: forum/skins/default/templates/faq.html:66
+#: forum/skins/default/templates/users/votes.html:17
+#: forum/views/commands.py:77
+msgid "downvote"
+msgstr "投反对票"
+
+#: forum/skins/default/templates/faq.html:69
+#, fuzzy
+msgid "open and close own questions"
+msgstr "打开关闭任何人的问题"
+
+#: forum/skins/default/templates/faq.html:73
+msgid "retag questions"
+msgstr "给任何问题整理标签"
+
+#: forum/skins/default/templates/faq.html:78
+msgid "edit community wiki questions"
+msgstr "编辑wiki类问题"
+
+#: forum/skins/default/templates/faq.html:83
+msgid "edit any answer"
+msgstr "编辑任何问题或答案"
+
+#: forum/skins/default/templates/faq.html:87
+#, fuzzy
+msgid "open any closed question"
+msgstr "打开关闭任何人的问题"
+
+#: forum/skins/default/templates/faq.html:91
+msgid "delete any comment"
+msgstr "删除任何一个评论"
+
+#: forum/skins/default/templates/faq.html:95
+msgid "delete any questions and answers and perform other moderation tasks"
+msgstr "删除任何一个问题或答案,及其他管理功能"
+
+#: forum/skins/default/templates/faq.html:103
+msgid "how to validate email title"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:105
+#, python-format
+msgid ""
+"how to validate email info with %(send_email_key_url)s %(gravatar_faq_url)s"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:110
+msgid "what is gravatar"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:111
+msgid "gravatar faq info"
+msgstr ""
+
+#: forum/skins/default/templates/faq.html:114
+msgid "To register, do I need to create new password?"
+msgstr "我需要注册一个新用户吗?"
+
+#: forum/skins/default/templates/faq.html:115
+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登录的"
+"帐号就可以使用系统。"
+
+#: forum/skins/default/templates/faq.html:116
+msgid "Login now!"
+msgstr "马上登录"
+
+#: forum/skins/default/templates/faq.html:121
+msgid "Why other people can edit my questions/answers?"
+msgstr "为什么其他人可以修改我的问题/回答?"
+
+#: forum/skins/default/templates/faq.html:122
+msgid "Goal of this site is..."
+msgstr "CNProg 是为了帮助程序员解决更多问题,更加方便的解决问题。"
+
+#: forum/skins/default/templates/faq.html:122
+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一样可编辑的,我们希望社区能帮助用户沉淀、积累更多有"
+"用的知识和经验。"
+
+#: forum/skins/default/templates/faq.html:123
+msgid "If this approach is not for you, we respect your choice."
+msgstr "如果您不喜欢这种方式,我们尊重你的选择。"
+
+#: forum/skins/default/templates/faq.html:127
+msgid "Still have questions?"
+msgstr "还有其他问题?"
+
+#: forum/skins/default/templates/faq.html:128
+#, fuzzy, python-format
+msgid ""
+"Please ask your question at %(ask_question_url)s, help make our community "
+"better!"
+msgstr "如果您对社区还有其他疑问,请一起来完善我们的"
+
+#: forum/skins/default/templates/faq.html:130
+#: forum/skins/default/templates/header.html:30
+#: forum/skins/default/templates/header.html:55 forum/views/readers.py:76
+msgid "questions"
+msgstr "问题"
+
+#: forum/skins/default/templates/faq.html:130
+msgid "."
+msgstr "。"
+
+#: forum/skins/default/templates/feedback.html:6
+#, fuzzy
+msgid "Feedback"
+msgstr "问题反馈"
+
+#: forum/skins/default/templates/feedback.html:11
+msgid "Give us your feedback!"
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:17
+#, python-format
+msgid ""
+"\n"
+"            <span class='big strong'>Dear %(user_name)s</span>, we look "
+"forward to hearing your feedback. \n"
+"            Please type and send us your message below.\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:24
+msgid ""
+"\n"
+"            <span class='big strong'>Dear visitor</span>, we look forward to "
+"hearing your feedback.\n"
+"            Please type and send us your message below.\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/feedback.html:41
+#, fuzzy
+msgid "(this field is required)"
+msgstr " 标签不能为空。"
+
+#: forum/skins/default/templates/feedback.html:49
+#, fuzzy
+msgid "Send Feedback"
+msgstr "问题反馈"
+
+# footer.html
+#: forum/skins/default/templates/footer.html:7
+#: forum/skins/default/templates/header.html:16
+#: forum/skins/default/templates/index.html:12
+msgid "about"
+msgstr "关于本站"
+
+#: forum/skins/default/templates/footer.html:8
+#: forum/skins/default/templates/header.html:17
+#: forum/skins/default/templates/index.html:13
+#: forum/skins/default/templates/question_edit_tips.html:22
+msgid "faq"
+msgstr "常见问题"
+
+#: forum/skins/default/templates/footer.html:9
+msgid "privacy policy"
+msgstr "隐私政策"
+
+#: forum/skins/default/templates/footer.html:18
+#, fuzzy
+msgid "give feedback"
+msgstr "问题反馈"
+
+#: forum/skins/default/templates/header.html:9
+msgid "administration"
+msgstr ""
+
+#: forum/skins/default/templates/header.html:12
+msgid "logout"
+msgstr "退出登录"
+
+#: forum/skins/default/templates/header.html:14
+msgid "login"
+msgstr "登录"
+
+#: forum/skins/default/templates/header.html:24
+msgid "back to home page"
+msgstr "回到首页"
+
+#: forum/skins/default/templates/header.html:32
+#: forum/skins/default/templates/header.html:57
+msgid "users"
+msgstr "用户"
+
+#: forum/skins/default/templates/header.html:33
+#: forum/skins/default/templates/users/signature.html:9
+#: forum/skins/default/templates/users/signature.html:15
+#: forum/skins/default/templates/users/signature.html:21
+#: forum/templatetags/extra_tags.py:167 forum/templatetags/extra_tags.py:196
+msgid "badges"
+msgstr "奖牌榜"
+
+#: forum/skins/default/templates/header.html:34
+msgid "unanswered questions"
+msgstr "没有回答的问题"
+
+#: forum/skins/default/templates/header.html:36
+msgid "ask a question"
+msgstr "我要提问"
+
+#: forum/skins/default/templates/header.html:51
+msgid "search"
+msgstr "搜索"
+
+#: forum/skins/default/templates/index.html:9
+#, fuzzy
+msgid "welcome to "
+msgstr "CNProg欢迎您!"
+
+#: forum/skins/default/templates/logout.html:6
+#: forum/skins/default/templates/logout.html:16
+msgid "Logout"
+msgstr "退出登录"
+
+#: forum/skins/default/templates/logout.html:19
+msgid ""
+"As a registered user you can login with your OpenID, log out of the site or "
+"permanently remove your account."
+msgstr ""
+"您是系统的<strong class=\"darkred\">注册</strong>用户,可以随时使用OpenID帐号"
+"登录系统或者注销登录。"
+
+#: forum/skins/default/templates/logout.html:20
+msgid "Logout now"
+msgstr "点击退出登录"
+
+#: forum/skins/default/templates/notarobot.html:3
+msgid "Please prove that you are a Human Being"
+msgstr ""
+
+#: forum/skins/default/templates/notarobot.html:10
+msgid "I am a Human Being"
+msgstr ""
+
+#: forum/skins/default/templates/pagesize.html:6
+msgid "posts per page"
+msgstr "每页显示:"
+
+#: forum/skins/default/templates/paginator.html:6
+#: forum/skins/default/templates/paginator.html:7
+msgid "previous"
+msgstr "上一页"
+
+#: forum/skins/default/templates/paginator.html:19
+msgid "current page"
+msgstr "当前页"
+
+#: forum/skins/default/templates/paginator.html:22
+#: forum/skins/default/templates/paginator.html:29
+msgid "page number "
+msgstr "第"
+
+#: forum/skins/default/templates/paginator.html:22
+#: forum/skins/default/templates/paginator.html:29
+msgid "number - make blank in english"
+msgstr "页"
+
+#: forum/skins/default/templates/paginator.html:33
+msgid "next page"
+msgstr "下一页"
+
+#: forum/skins/default/templates/post_contributor_info.html:9
+#, python-format
+msgid ""
+"\n"
+"                one revision\n"
+"            "
+msgid_plural ""
+"\n"
+"                %(rev_count)s revisions\n"
+"            "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/post_contributor_info.html:24
+#, fuzzy
+msgid "posted"
+msgstr "投赞成票"
+
+#: forum/skins/default/templates/post_contributor_info.html:45
+msgid "updated"
+msgstr "更新于"
+
+#: forum/skins/default/templates/privacy.html:6
+#: forum/skins/default/templates/privacy.html:11
+msgid "Privacy policy"
+msgstr "隐私政策"
+
+#: forum/skins/default/templates/privacy.html:15
+msgid "general message about privacy"
+msgstr ""
+"CNProg承认用户隐私的重要性。本文件概述在您浏览CNProg过程中所接收和收集的个人"
+"信息的种类,以及CNProg所采取的保护信息的一些措施。CNProg希望这将有助于您在知"
+"情的情况下,就和我们 共享个人信息的问题作出决定。"
+
+#: forum/skins/default/templates/privacy.html:18
+msgid "Site Visitors"
+msgstr "网站访问者"
+
+#: forum/skins/default/templates/privacy.html:20
+msgid "what technical information is collected about visitors"
+msgstr ""
+"当您访问本网站或使用我们的某些在线服务时,服务器会自动记录信息,包括但不限于"
+"URL、IP地址、浏览器的类型、屏幕分辨率、系统类型和使用的语言以及访问日期和时"
+"间。我们的目的是为了向您>提供更好的用户服务,包括可能为您提供定制的在线服务。"
+
+#: forum/skins/default/templates/privacy.html:23
+msgid "Personal Information"
+msgstr "个人身份信息"
+
+#: forum/skins/default/templates/privacy.html:25
+msgid "details on personal information policies"
+msgstr ""
+"在登录使用CNProg的提问和回答功能时,我们要求使用者提供用户名、密码、电子邮件"
+"等信息。CNProg收集这类关于个人身份的信息只是为了登录系统获得使用功能的目的。"
+"我们不会向任何其他社区用 户、个人或第三方透露您的密码或者电子邮件信息。用户可"
+"以选择性地填写用户资料、个人网站、年龄、城市等信息,我们收集这些内容为了使用"
+"户能够更容易和更满意地使用CNProg提供的网页和服务。"
+
+#: forum/skins/default/templates/privacy.html:28
+msgid "Other Services"
+msgstr "其他服务"
+
+#: forum/skins/default/templates/privacy.html:30
+msgid "details on sharing data with third parties"
+msgstr ""
+"CNProg可能会收集和统计用户访问本站的概况数据。例如,CNProg可能会检测网站最流"
+"行的部分功能。CNProg可能会公开显示或者提供给第三方使用该数据。但是,CNProg不"
+"会公开您的身份信息。"
+
+#: forum/skins/default/templates/privacy.html:35
+msgid "cookie policy details"
+msgstr ""
+"访问CNProg时,我们会向您的计算机发送一个或多个专门用于识别您的浏览器的Cookie"
+"(包含一个字符串的小文件)。 使用 Cookie 的目的是通过储存用户偏好、跟踪用户倾"
+"向(例如搜索方法)来提高我们的服务质量。大多数浏览器的初始设置均为接受 "
+"Cookie,但也可以将其重置为拒绝所有 Cookie 或在收到 Cookie 时提示。不过,如果"
+"禁用 Cookie,某些功能和服务可能无法正常运行。"
+
+#: forum/skins/default/templates/privacy.html:37
+msgid "Policy Changes"
+msgstr "政策更改"
+
+#: forum/skins/default/templates/privacy.html:38
+#, fuzzy
+msgid "how privacy policies can be changed"
+msgstr ""
+"我们可能在事先通知或不通知的情况下随时更改此'隐私政策',我们建议用户时常查看"
+"CNProg隐私政策的改动,在任何改动生效后您的继续访问和使用本站,我们假设您已同"
+"意了CNProg以上的所有条款。"
+
+# this is how above two are supposed to be
+#: forum/skins/default/templates/question.html:70
+#: forum/skins/default/templates/sidebar/recent_tags.html:9
+#, fuzzy, python-format
+msgid "see questions tagged '%(tagname)s'"
+msgstr "查看有关'%(tagname)s'的问题"
+
+#: forum/skins/default/templates/question.html:87
+#, fuzzy, python-format
+msgid ""
+"The question has been closed for the following reason \"%(close_reason)s\" by"
+msgstr "问题以“%s”的原因已被"
+
+#: forum/skins/default/templates/question.html:89
+#, fuzzy, python-format
+msgid "close date %(closed_at)s"
+msgstr "由于以下原因,你要关闭这个问题"
+
+#: forum/skins/default/templates/question.html:97
+#, python-format
+msgid ""
+"\n"
+"                    One Answer:\n"
+"                    "
+msgid_plural ""
+"\n"
+"                    %(counter)s Answers:\n"
+"                    "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/question.html:105
+msgid "oldest answers will be shown first"
+msgstr "最先回答显示在最前面"
+
+#: forum/skins/default/templates/question.html:105
+msgid "oldest answers"
+msgstr "最先回答"
+
+#: forum/skins/default/templates/question.html:107
+msgid "newest answers will be shown first"
+msgstr "最晚回答显示在最前面"
+
+#: forum/skins/default/templates/question.html:107
+msgid "newest answers"
+msgstr "最近回答"
+
+#: forum/skins/default/templates/question.html:109
+msgid "most voted answers will be shown first"
+msgstr "投票次数最多的显示在最前面"
+
+#: forum/skins/default/templates/question.html:109
+msgid "popular answers"
+msgstr "投票最多"
+
+#: forum/skins/default/templates/question.html:157
+msgid "Your answer"
+msgstr "您的回答"
+
+#: forum/skins/default/templates/question.html:159
+#, fuzzy
+msgid "Be the first one to answer this question!"
+msgstr "不是一个可以回答的“问题”"
+
+#: forum/skins/default/templates/question.html:165
+msgid "you can answer anonymously and then login"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:169
+msgid "answer your own question only to give an answer"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:171
+#, fuzzy
+msgid "please only give an answer, no discussions"
+msgstr "建议您提的问题是可以被答复的,而不仅仅是可以讨论。"
+
+#: forum/skins/default/templates/question.html:207
+msgid "Login/Signup to Post Your Answer"
+msgstr ""
+
+#: forum/skins/default/templates/question.html:210
+#, fuzzy
+msgid "Answer Your Own Question"
+msgstr "回答该问题"
+
+#: forum/skins/default/templates/question.html:212
+msgid "Answer the question"
+msgstr "回答该问题"
+
+#: forum/skins/default/templates/question.html:229
+msgid "Question tags"
+msgstr "您正在浏览的问题含有以下标签"
+
+#: forum/skins/default/templates/question.html:239
+#, fuzzy
+msgid "question asked"
+msgstr "提问时间"
+
+#: forum/skins/default/templates/question.html:242
+msgid "question was seen"
+msgstr "目前浏览数量"
+
+#: forum/skins/default/templates/question.html:242
+msgid "times"
+msgstr "次"
+
+#: forum/skins/default/templates/question.html:245
+msgid "last updated"
+msgstr "最后更新时间"
+
+#: forum/skins/default/templates/question.html:250
+#, fuzzy
+msgid "Related questions"
+msgstr "相似的问题"
+
+# page title
+#: forum/skins/default/templates/question_edit.html:5
+#: forum/skins/default/templates/question_edit.html:63
+msgid "Edit question"
+msgstr "修改问题"
+
+#: forum/skins/default/templates/question_edit_tips.html:4
+msgid "question tips"
+msgstr "受欢迎的提问"
+
+#: forum/skins/default/templates/question_edit_tips.html:9
+#, python-format
+msgid ""
+"\n"
+"                ask a question relevant to the %(app_title)s community \n"
+"                "
+msgstr ""
+
+#: forum/skins/default/templates/question_edit_tips.html:15
+#, fuzzy
+msgid "please try provide enough details"
+msgstr "请详细描述您的问题。"
+
+#: forum/skins/default/templates/question_retag.html:5
+#: forum/skins/default/templates/question_retag.html:56
+msgid "Change tags"
+msgstr "修改问题标签"
+
+# todo: remove magic numbers from this file
+#: forum/skins/default/templates/question_retag.html:44
+msgid "up to 5 tags, less than 20 characters each"
+msgstr "最多5个标签,每个标签长度小于20个字符。"
+
+#: forum/skins/default/templates/question_retag.html:86
+msgid "Why use and modify tags?"
+msgstr "为什么我只能修改问题标签?"
+
+#: forum/skins/default/templates/question_retag.html:89
+#, fuzzy
+msgid "tags help us keep Questions organized"
+msgstr "CNProg用标签来分类系统的信息"
+
+#: forum/skins/default/templates/question_retag.html:97
+msgid "tag editors receive special awards from the community"
+msgstr "修改标签的用户将授予特殊的社区奖牌"
+
+#: forum/skins/default/templates/questions.html:7
+msgid "Questions"
+msgstr "问题列表"
+
+#: forum/skins/default/templates/reopen.html:6
+#: forum/skins/default/templates/reopen.html:16
+msgid "Reopen question"
+msgstr "重设问题"
+
+#: forum/skins/default/templates/reopen.html:19
+msgid "Open the previously closed question"
+msgstr "你将打开这个已经被关闭的问题"
+
+#: forum/skins/default/templates/reopen.html:22
+#, fuzzy
+msgid "The question was closed for the following reason "
+msgstr "问题曾以"
+
+#: forum/skins/default/templates/reopen.html:22
+msgid "reason - leave blank in english"
+msgstr "的原因被"
+
+#: forum/skins/default/templates/reopen.html:22
+#, fuzzy
+msgid "on "
+msgstr "于"
+
+#: forum/skins/default/templates/reopen.html:22
+msgid "date closed"
+msgstr "关闭"
+
+#: forum/skins/default/templates/reopen.html:29
+#, fuzzy
+msgid "Reopen this question"
+msgstr "确定打开这个问题"
+
+# revisions_answer.html
+#: forum/skins/default/templates/revisions_answer.html:7
+#: forum/skins/default/templates/revisions_answer.html:36
+#: forum/skins/default/templates/revisions_question.html:7
+#: forum/skins/default/templates/revisions_question.html:35
+msgid "Revision history"
+msgstr "版本历史"
+
+#: forum/skins/default/templates/revisions_answer.html:48
+#: forum/skins/default/templates/revisions_question.html:47
+msgid "click to hide/show revision"
+msgstr ""
+
+#: forum/skins/default/templates/revisions_answer.html:56
+#: forum/templatetags/node_tags.py:62
+msgid "edit"
+msgstr "编辑"
+
+#: forum/skins/default/templates/subscription_status.html:3
+#, fuzzy
+msgid "Subscription"
+msgstr "提问"
+
+#: forum/skins/default/templates/subscription_status.html:8
+msgid "You were automatically subscribed to this question."
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:10
+#, fuzzy
+msgid "You are subscribed to this question."
+msgstr "订阅最>新问题"
+
+#: forum/skins/default/templates/subscription_status.html:13
+#, fuzzy
+msgid "You are not subscribed to this question."
+msgstr "订阅最>新问题"
+
+#: forum/skins/default/templates/subscription_status.html:18
+#: forum/views/commands.py:323
+msgid "unsubscribe me"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:20
+#: forum/views/commands.py:323
+msgid "subscribe me"
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:24
+#, python-format
+msgid ""
+"\n"
+"            (you can adjust your notification settings on your <a href=\"%"
+"(profile_url)s?sort=email_subscriptions\">profile</a>)\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/subscription_status.html:29
+msgid "Once you sign in you will be able to subscribe for any updates here"
+msgstr ""
+
+# book.html line 123 must be empty in english
+#: forum/skins/default/templates/tag_selector.html:4
+#: forum/skins/default/templates/question_list/tag_selector.html:6
+#, fuzzy
+msgid "Interesting tags"
+msgstr "的问题"
+
+# this is how above two are supposed to be
+#: forum/skins/default/templates/tag_selector.html:10
+#: forum/skins/default/templates/tag_selector.html:27
+#: forum/skins/default/templates/question_list/related_tags.html:9
+#: forum/skins/default/templates/question_list/tag_selector.html:12
+#: forum/skins/default/templates/question_list/tag_selector.html:29
+#, fuzzy, python-format
+msgid "see questions tagged '%(tag_name)s'"
+msgstr "查看有关'%(tagname)s'的问题"
+
+#: forum/skins/default/templates/tag_selector.html:14
+#: forum/skins/default/templates/question_list/tag_selector.html:16
+#, python-format
+msgid "remove '%(tag_name)s' from the list of interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:20
+#: forum/skins/default/templates/tag_selector.html:37
+#: forum/skins/default/templates/question_list/tag_selector.html:22
+#: forum/skins/default/templates/question_list/tag_selector.html:39
+msgid "Add"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:21
+#: forum/skins/default/templates/question_list/tag_selector.html:23
+#, fuzzy
+msgid "Ignored tags"
+msgstr "修改问题标签"
+
+#: forum/skins/default/templates/tag_selector.html:31
+#: forum/skins/default/templates/question_list/tag_selector.html:33
+#, python-format
+msgid "remove '%(tag_name)s' from the list of ignored tags"
+msgstr ""
+
+#: forum/skins/default/templates/tag_selector.html:40
+#: forum/skins/default/templates/question_list/tag_selector.html:42
+#, fuzzy
+msgid "keep ignored questions hidden"
+msgstr "打开关闭任何人的问题"
+
+#: forum/skins/default/templates/tags.html:6
+#: forum/skins/default/templates/tags.html:30
+msgid "Tag list"
+msgstr "标签列表"
+
+#: forum/skins/default/templates/tags.html:32
+msgid "sorted alphabetically"
+msgstr "按名称的字母先后顺序排序"
+
+#: forum/skins/default/templates/tags.html:32
+msgid "by name"
+msgstr "按名称排序"
+
+#: forum/skins/default/templates/tags.html:33
+msgid "sorted by frequency of tag use"
+msgstr "按标签被使用的次数排序"
+
+#: forum/skins/default/templates/tags.html:33
+#, fuzzy
+msgid "by popularity"
+msgstr "按流行程度排序"
+
+#: forum/skins/default/templates/tags.html:39
+msgid "All tags matching query"
+msgstr "匹配查询"
+
+#: forum/skins/default/templates/tags.html:39
+msgid "all tags - make this empty in english"
+msgstr "的所有标签"
+
+#: forum/skins/default/templates/tags.html:42
+#, fuzzy
+msgid "Nothing found"
+msgstr "没有找到相关数据。"
+
+#: forum/skins/default/templates/auth/auth_settings.html:5
+#: forum/skins/default/templates/auth/auth_settings.html:7
+msgid "Authentication settings"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:9
+msgid ""
+"These are the external authentication providers currently associated with "
+"your account."
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:12
+#, fuzzy
+msgid "remove"
+msgstr "打开"
+
+#: forum/skins/default/templates/auth/auth_settings.html:17
+msgid ""
+"You currently have no external authentication provider associated with your "
+"account."
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:19
+msgid "Add new provider"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:21
+msgid "This is where you can change your password. Make sure you remember it!"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:24
+msgid ""
+"You can set up a password for your account, so you can login using standard "
+"username and password!"
+msgstr ""
+
+#: forum/skins/default/templates/auth/auth_settings.html:31
+#, fuzzy
+msgid "Create password"
+msgstr "确认密码"
+
+#: forum/skins/default/templates/auth/complete.html:5
+msgid "Connect your OpenID with this site"
+msgstr "绑定OpenID"
+
+#: forum/skins/default/templates/auth/complete.html:8
+msgid "Connect your OpenID with your account on this site"
+msgstr "绑定OpenID帐号"
+
+#: forum/skins/default/templates/auth/complete.html:12
+msgid "You are here for the first time with "
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:13
+msgid ""
+"Please create your screen name and save your email address. Saved email "
+"address will let you subscribe for the updates on the most interesting "
+"questions and will be used to create and retrieve your unique avatar image. "
+msgstr ""
+
+# todo: review this message may be confusing user
+#: forum/skins/default/templates/auth/complete.html:15
+msgid "This account already exists, please use another."
+msgstr "输入您的新帐号或者指定已经存在的帐号。"
+
+#: forum/skins/default/templates/auth/complete.html:30
+msgid "Sorry, looks like we have some errors:"
+msgstr "请注意以下错误:"
+
+#: forum/skins/default/templates/auth/complete.html:47
+msgid "Screen name label"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:54
+#, fuzzy
+msgid "Email address label"
+msgstr "您的电子邮件地址"
+
+#: forum/skins/default/templates/auth/complete.html:60
+#: forum/skins/default/templates/auth/signup.html:18
+msgid "receive updates motivational blurb"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:64
+#: forum/skins/default/templates/auth/signup.html:22
+msgid "please select one of the options above"
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:67
+msgid "Tag filter tool will be your right panel, once you log in."
+msgstr ""
+
+#: forum/skins/default/templates/auth/complete.html:68
+msgid "create account"
+msgstr "创建帐号"
+
+#: forum/skins/default/templates/auth/complete.html:77
+msgid "Existing account"
+msgstr "已经存在的用户"
+
+#: forum/skins/default/templates/auth/complete.html:78
+msgid "user name"
+msgstr "用户名"
+
+#: forum/skins/default/templates/auth/complete.html:79
+msgid "password"
+msgstr "密码"
+
+#: forum/skins/default/templates/auth/complete.html:86
+msgid "Register"
+msgstr "确认"
+
+#: forum/skins/default/templates/auth/complete.html:87
+msgid "Forgot your password?"
+msgstr "忘记密码?"
+
+#: forum/skins/default/templates/auth/email_validation.html:6
+#: forum/skins/default/templates/auth/temp_login_email.html:6
+msgid "Greetings from the Q&A forum"
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:8
+msgid "To make use of the Forum, please follow the link below:"
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:12
+msgid "Following the link above will help us verify your email address."
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:14
+#: forum/skins/default/templates/auth/temp_login_email.html:14
+msgid ""
+"If you beleive that this message was sent in mistake -\n"
+"    no further action is needed. Just ingore this email, we apologize\n"
+"    for any inconvenience"
+msgstr ""
+
+#: forum/skins/default/templates/auth/email_validation.html:18
+#: forum/skins/default/templates/auth/temp_login_email.html:18
+#: forum/skins/default/templates/notifications/answeraccepted.html:15
+#: forum/skins/default/templates/notifications/newanswer.html:25
+#: forum/skins/default/templates/notifications/newcomment.html:32
+#: forum/skins/default/templates/notifications/newmember.html:15
+#: forum/skins/default/templates/notifications/newquestion.html:25
+msgid ""
+"Sincerely,<br />\n"
+"    Forum Administrator"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:6
+msgid "Login"
+msgstr "登录"
+
+#: forum/skins/default/templates/auth/signin.html:24
+msgid "User login"
+msgstr "用户登录"
+
+#: forum/skins/default/templates/auth/signin.html:36
+#: forum/skins/default/templates/auth/signin.html:86
+#: forum/skins/default/templates/auth/signin.html:92
+msgid "Or..."
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:39
+msgid "Click to sign in through any of these services."
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:44
+msgid "Validate my email after I login."
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:94
+#, fuzzy
+msgid "Click"
+msgstr "链接"
+
+#: forum/skins/default/templates/auth/signin.html:94
+msgid "if you're having troubles signing in."
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:98
+msgid "Enter your "
+msgstr ""
+
+#: forum/skins/default/templates/auth/signin.html:154
+msgid "Why use OpenID?"
+msgstr "为什么需要OpenID登录?"
+
+#: forum/skins/default/templates/auth/signin.html:157
+msgid "with openid it is easier"
+msgstr ""
+"构建在OpenID网络认证上的本系统,不需要你注册新的帐号,即可使用我们系统的所有"
+"功能"
+
+#: forum/skins/default/templates/auth/signin.html:160
+msgid "reuse openid"
+msgstr "用同一个帐号可登录互联网所有激活OpenID的网站"
+
+#: forum/skins/default/templates/auth/signin.html:163
+msgid "openid is widely adopted"
+msgstr "全世界有1.6亿OpenID帐号,和10,000个支持OpenID的站点"
+
+#: forum/skins/default/templates/auth/signin.html:166
+msgid "openid is supported open standard"
+msgstr "OpenID是有开放标准,并且有相关的基金组织提供支持"
+
+#: forum/skins/default/templates/auth/signin.html:171
+msgid "Find out more"
+msgstr "查看更多"
+
+#: forum/skins/default/templates/auth/signin.html:172
+msgid "Get OpenID"
+msgstr "获取OpenID"
+
+#: forum/skins/default/templates/auth/signup.html:4
+msgid "Signup"
+msgstr "注册帐号"
+
+#: forum/skins/default/templates/auth/signup.html:8
+#, fuzzy
+msgid "Create login name and password"
+msgstr "使用帐号密码登录"
+
+#: forum/skins/default/templates/auth/signup.html:10
+msgid "Traditional signup info"
+msgstr ""
+
+#: forum/skins/default/templates/auth/signup.html:31
+#, fuzzy
+msgid "Create Account"
+msgstr "创建帐号"
+
+#: forum/skins/default/templates/auth/signup.html:32
+msgid "or"
+msgstr "或者"
+
+#: forum/skins/default/templates/auth/signup.html:33
+#, fuzzy
+msgid "return to login page"
+msgstr "返回登录"
+
+#: forum/skins/default/templates/auth/temp_login_email.html:8
+msgid "You're seeing this because someone requested a temporary login link"
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_email.html:12
+msgid "Following the link above will give you access to your account."
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:5
+msgid "Request temporary login key"
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:7
+msgid "Account: request temporary login key"
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:8
+msgid ""
+"\n"
+"    If you're experiencing problems accessing your account, or if you forgot "
+"your password,\n"
+"    here you can request a temporary login key. Fill out your account email "
+"and we'll send you a temporary access link that\n"
+"    will enable you to access your account. This token is valid only once "
+"and for a limited period of time.\n"
+" "
+msgstr ""
+
+#: forum/skins/default/templates/auth/temp_login_request.html:25
+#, fuzzy
+msgid "Send link"
+msgstr "链接"
+
+#: forum/skins/default/templates/node/accept_button.html:5
+#, fuzzy, python-format
+msgid "%(who)s has selected this answer as the correct answer"
+msgstr "这个答案已经被提问作者标记为最佳答案"
+
+#: forum/skins/default/templates/node/accept_button.html:5
+#, fuzzy
+msgid "mark this answer as the accepted answer"
+msgstr "有答案已被接受为正确答案"
+
+#: forum/skins/default/templates/node/comments.html:22
+#, fuzzy
+msgid "I like this comment (click again to cancel)"
+msgstr "这篇帖子有价值(再次点击取消操作)"
+
+#: forum/skins/default/templates/node/comments.html:26
+#, fuzzy
+msgid "Edit comment"
+msgstr "添加评论"
+
+#: forum/skins/default/templates/node/comments.html:30
+#, fuzzy
+msgid "Delete comment"
+msgstr "删除任何一个评论"
+
+#: forum/skins/default/templates/node/comments.html:42
+#, python-format
+msgid "showing %(showing)s of %(total)s"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:44
+msgid "show all"
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:47
+#, fuzzy
+msgid "add new comment"
+msgstr "添加评论"
+
+#: forum/skins/default/templates/node/comments.html:55
+#, fuzzy
+msgid " add comment"
+msgstr "添加评论"
+
+#: forum/skins/default/templates/node/comments.html:58
+#, python-format
+msgid ""
+"\n"
+"                have <span class=\"comments-char-left-count\">%(max_length)"
+"s</span> characters left\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/node/comments.html:71
+#, fuzzy
+msgid "just now"
+msgstr "点击退出登录"
+
+#: forum/skins/default/templates/node/favorite_mark.html:3
+#, fuzzy
+msgid "mark/unmark this question as favorite (click again to cancel)"
+msgstr "我要收藏这个问题(再次点击取消操作)"
+
+#: forum/skins/default/templates/node/vote_buttons.html:3
+#, fuzzy
+msgid "I like this post (click again to cancel)"
+msgstr "这篇帖子有价值(再次点击取消操作)"
+
+#: forum/skins/default/templates/node/vote_buttons.html:7
+msgid "current number of votes"
+msgstr "当前总票数"
+
+#: forum/skins/default/templates/node/vote_buttons.html:10
+#, fuzzy
+msgid "I dont like this post (click again to cancel)"
+msgstr "这篇帖子没有价值(再次点击取消操作)"
+
+#: forum/skins/default/templates/notifications/answeraccepted.html:6
+#: forum/skins/default/templates/notifications/digest.html:7
+#: forum/skins/default/templates/notifications/newanswer.html:6
+#: forum/skins/default/templates/notifications/newcomment.html:6
+#: forum/skins/default/templates/notifications/newmember.html:6
+#: forum/skins/default/templates/notifications/newquestion.html:6
+msgid "Hello"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/answeraccepted.html:9
+#, python-format
+msgid ""
+"\n"
+"        Just to let you know that %(accepter)s has just accepted %"
+"(answer_author)s's answer on his question\n"
+"        <a href=\"%(app_url)s%(question_url)s\">%(question_title)s</a>:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:9
+#, python-format
+msgid ""
+"\n"
+"    This is the %(digest_type)s activity digest for %(app_title)s\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:15
+#, python-format
+msgid ""
+"\n"
+"            %(nusers_count)s new user%(nusers_count_pluralize)s joined the %"
+"(app_title)s community:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:28
+#, python-format
+msgid ""
+"\n"
+"            %(question_count)s of your subscriptions have updates:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:35
+#, fuzzy
+msgid "On question "
+msgstr "提问"
+
+#: forum/skins/default/templates/notifications/digest.html:37
+#, python-format
+msgid ""
+"\n"
+"                    %(answer_count)s new answer%(answer_count_pluralize)s\n"
+"                "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:42
+#, python-format
+msgid ""
+"\n"
+"                    %(comment_count)s new comment%(comment_count_pluralize)"
+"s\n"
+"                "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:46
+#, fuzzy
+msgid "on your own post(s)"
+msgstr "获取您自己的"
+
+#: forum/skins/default/templates/notifications/digest.html:50
+#, fuzzy
+msgid "an answer was accepted"
+msgstr "问题已经解决,已得到正确答案"
+
+#: forum/skins/default/templates/notifications/digest.html:59
+#, python-format
+msgid ""
+"\n"
+"            %(question_count)s new question%(question_count_pluralize)s\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:63
+msgid "matching your interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/digest.html:65
+#, fuzzy
+msgid "posted :"
+msgstr "投赞成票"
+
+#: forum/skins/default/templates/notifications/digest.html:71
+#, python-format
+msgid ""
+"\n"
+"                    Posted by %(author_name)s in %(question_time)s\n"
+"                "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:7
+#, python-format
+msgid ""
+"\n"
+"    Hello, this is a %(site_title)s forum feedback message\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:13
+msgid "Sender"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:15
+#: forum/skins/default/templates/notifications/feedback.html:18
+#: forum/skins/default/templates/users/info.html:93
+msgid "email"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:17
+msgid "anonymous"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/feedback.html:25
+msgid "Message body:"
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newanswer.html:9
+#, python-format
+msgid ""
+"\n"
+"        %(author_name)s has just posted a new answer on %(app_title)s to the "
+"question\n"
+"        <a href=\"%(app_url)s%(question_url)s\">%(question_title)s\"</a>:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newanswer.html:20
+#: forum/skins/default/templates/notifications/newcomment.html:28
+#: forum/skins/default/templates/notifications/newquestion.html:20
+msgid ""
+"\n"
+"        Don't forget to come over and cast your vote.\n"
+"    "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newcomment.html:9
+#, python-format
+msgid ""
+"\n"
+"            %(author_name)s has just posted a comment on\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newcomment.html:14
+#, python-format
+msgid ""
+"\n"
+"                the answer posted by <a href=\"%(app_url)s%(poster_url)s\">%"
+"(poster_name)s</a> to\n"
+"            "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newcomment.html:19
+#, python-format
+msgid ""
+"\n"
+"             the question  <a href=\"%(app_url)s%(question_url)s\">%"
+"(question_title)s</a>\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newmember.html:9
+#, python-format
+msgid ""
+"\n"
+"        %(newmember_name)s has just joined %(app_title)s. You can visit %"
+"(newmember_name)s's profile using the following link: <br />\n"
+"        <a href=\"%(app_url)s%(newmember_url)s\">%(newmember_name)s profile</"
+"a>\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/notifications/newquestion.html:9
+#, python-format
+msgid ""
+"\n"
+"        %(author_name)s has just posted a new question on %(app_title)s, "
+"with title\n"
+"        <a href=\"%(app_url)s%(question_url)s\">%(question_title)s</a> and "
+"tagged <em>%(question_tags)s</em>:\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/base.html:13
+msgid "OSQA administration area"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/base.html:26
+msgid "Administration menu"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:7
+msgid "Dashboard"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:10
+msgid "Welcome to the OSQA administration area."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:17
+#, fuzzy
+msgid "Site statistics"
+msgstr "网站访问者"
+
+#: forum/skins/default/templates/osqaadmin/index.html:21
+#: forum/skins/default/templates/osqaadmin/index.html:26
+msgid "in the last 24 hours"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:31
+#, fuzzy
+msgid "user"
+msgstr "用户"
+
+#: forum/skins/default/templates/osqaadmin/index.html:31
+msgid "joined in the last 24 hours"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:37
+#, fuzzy
+msgid "Site status"
+msgstr "网站访问者"
+
+#: forum/skins/default/templates/osqaadmin/index.html:42
+msgid ""
+"Your site is running in bootstrap mode, click the button bellow to revert to "
+"defaults."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:45
+msgid ""
+"Your site is running in standard mode, click the button bellow to run in "
+"bootstrap mode."
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:47
+msgid ""
+"Your site is running with some customized settings, click the buttons bellow "
+"to run with defaults or in bootstrap mode"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:51
+msgid "Are you sure you want to revert to the defaults?"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:51
+msgid "revert to defaults"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:54
+msgid "Are you sure you want to run bootstrap mode?"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:54
+msgid "go bootstrap"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:59
+msgid "Recalculate scores and reputation"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:60
+msgid "This is a heavy operation, are you sure?"
+msgstr ""
+
+#: forum/skins/default/templates/osqaadmin/index.html:60
+#, fuzzy
+msgid "Recalculate"
+msgstr "真实姓名"
+
+#: forum/skins/default/templates/osqaadmin/index.html:65
+#, fuzzy
+msgid "Recent activity"
+msgstr "最近活动"
+
+#: forum/skins/default/templates/question_list/item.html:12
+#, fuzzy
+msgid "this question has an accepted answer"
+msgstr "这个问题被"
+
+#: forum/skins/default/templates/question_list/related_tags.html:6
+msgid "Related tags"
+msgstr "相关标签"
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:4
+msgid "most recently updated questions"
+msgstr "最近被更新的问题"
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:4
+#, fuzzy
+msgid "active"
+msgstr "活跃问题"
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:5
+msgid "most recently asked questions"
+msgstr "最新加入系统的问题"
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:5
+msgid "newest"
+msgstr "最新问题"
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:6
+msgid "hottest questions"
+msgstr "被回复最多的问题"
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:6
+msgid "hottest"
+msgstr "热门问题"
+
+#: forum/skins/default/templates/question_list/sort_tabs.html:7
+msgid "most voted questions"
+msgstr "投票次数最多的问题"
+
+# "最有价值问题"
+# "最新问题"
+#: forum/skins/default/templates/question_list/sort_tabs.html:7
+msgid "most voted"
+msgstr "最有价值的问题"
+
+#: forum/skins/default/templates/question_list/title.html:5
+msgid "Found by tags"
+msgstr "标签问题"
+
+#: forum/skins/default/templates/question_list/title.html:9
+msgid "Search results"
+msgstr ""
+
+#: forum/skins/default/templates/question_list/title.html:11
+msgid "Found by title"
+msgstr "查询结果"
+
+#: forum/skins/default/templates/question_list/title.html:15
+msgid "Unanswered questions"
+msgstr "没有回答的问题"
+
+#: forum/skins/default/templates/question_list/title.html:17
+#: forum/skins/default/templates/users/subscriptions.html:74
+msgid "All questions"
+msgstr "所有问题"
+
+#: forum/skins/default/templates/sidebar/recent_awards.html:4
+msgid "Recent awards"
+msgstr "最新奖牌"
+
+#: forum/skins/default/templates/sidebar/recent_awards.html:15
+msgid "all awards"
+msgstr "所有奖牌"
+
+#: forum/skins/default/templates/sidebar/recent_tags.html:4
+msgid "Recent tags"
+msgstr "最新标签"
+
+#: forum/skins/default/templates/sidebar/recent_tags.html:12
+msgid "popular tags"
+msgstr "受欢迎的标签"
+
+#: forum/skins/default/templates/users/edit.html:6
+msgid "Edit user profile"
+msgstr "修改个人资料"
+
+#: forum/skins/default/templates/users/edit.html:19
+msgid "edit profile"
+msgstr "修改资料"
+
+#: forum/skins/default/templates/users/edit.html:31
+msgid "image associated with your email address"
+msgstr "和您的邮件地址是绑定的"
+
+#: forum/skins/default/templates/users/edit.html:31
+#, python-format
+msgid "avatar, see %(gravatar_faq_url)s"
+msgstr ""
+
+#: forum/skins/default/templates/users/edit.html:36
+#: forum/skins/default/templates/users/info.html:52
+msgid "Registered user"
+msgstr "注册用户"
+
+#: forum/skins/default/templates/users/edit.html:43
+#, fuzzy
+msgid "Screen Name"
+msgstr "当前页"
+
+#: forum/skins/default/templates/users/edit.html:86
+#: forum/skins/default/templates/users/subscriptions.html:116
+msgid "Update"
+msgstr "更新"
+
+#: forum/skins/default/templates/users/info.html:22
+#: forum/skins/default/templates/users/signature.html:6
+#: forum/skins/default/templates/users/users.html:26
+msgid "reputation"
+msgstr "积分"
+
+#: forum/skins/default/templates/users/info.html:32
+msgid "Moderate this user"
+msgstr ""
+
+#: forum/skins/default/templates/users/info.html:44
+msgid "update profile"
+msgstr "更新我的资料"
+
+#: forum/skins/default/templates/users/info.html:56
+msgid "real name"
+msgstr "姓名"
+
+#: forum/skins/default/templates/users/info.html:61
+msgid "member for"
+msgstr "已加入"
+
+#: forum/skins/default/templates/users/info.html:66
+msgid "last seen"
+msgstr "上次活动时间"
+
+#: forum/skins/default/templates/users/info.html:72
+msgid "user website"
+msgstr "个人网站"
+
+#: forum/skins/default/templates/users/info.html:78
+msgid "location"
+msgstr "城市"
+
+# user_info.html 
+#: forum/skins/default/templates/users/info.html:86
+msgid "age"
+msgstr "年龄"
+
+#: forum/skins/default/templates/users/info.html:87
+msgid "age unit"
+msgstr "岁"
+
+#: forum/skins/default/templates/users/info.html:100
+msgid "todays unused votes"
+msgstr "今日剩余投票数"
+
+#: forum/skins/default/templates/users/info.html:101
+msgid "votes left"
+msgstr "票"
+
+#: forum/skins/default/templates/users/stats.html:13
+#, python-format
+msgid ""
+"\n"
+"                <span class=\"count\">1</span> Question\n"
+"                "
+msgid_plural ""
+"\n"
+"                <span class=\"count\">%(counter)s</span> Questions\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:29
+#, python-format
+msgid ""
+"\n"
+"                <span class=\"count\">1</span> Answer\n"
+"                "
+msgid_plural ""
+"\n"
+"                <span class=\"count\">%(counter)s</span> Answers\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:42
+#, fuzzy, python-format
+msgid "the answer has been voted for %(vote_count)s times"
+msgstr "该回答总共有%d个投票"
+
+#: forum/skins/default/templates/users/stats.html:42
+msgid "this answer has been selected as correct"
+msgstr "该回答已被设为最佳答案"
+
+#: forum/skins/default/templates/users/stats.html:58
+#, python-format
+msgid ""
+"\n"
+"                    <span class=\"count\">1</span> Vote\n"
+"                "
+msgid_plural ""
+"\n"
+"                    <span class=\"count\">%(cnt)s</span> Votes\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:69
+msgid "thumb up"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:70
+msgid "user has voted up this many times"
+msgstr "该用户投的赞成票总数"
+
+#: forum/skins/default/templates/users/stats.html:74
+msgid "thumb down"
+msgstr ""
+
+#: forum/skins/default/templates/users/stats.html:75
+#, fuzzy
+msgid "user voted down this many times"
+msgstr "用户投的反对票总数"
+
+#: forum/skins/default/templates/users/stats.html:84
+#, python-format
+msgid ""
+"\n"
+"                    <span class=\"count\">1</span> Tag\n"
+"                "
+msgid_plural ""
+"\n"
+"                    <span class=\"count\">%(counter)s</span> Tags\n"
+"                "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/stats.html:97
+#, fuzzy, python-format
+msgid ""
+"see other questions with %(view_user)s's contributions tagged '%(tag_name)s' "
+msgstr "查看有关'%s'的问题"
+
+#: forum/skins/default/templates/users/stats.html:112
+#, python-format
+msgid ""
+"\n"
+"            <span class=\"count\">1</span> Badge\n"
+"            "
+msgid_plural ""
+"\n"
+"            <span class=\"count\">%(counter)s</span> Badges\n"
+"            "
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/skins/default/templates/users/subscriptions.html:8
+msgid "Notifications and subscription settings"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:10
+msgid ""
+"\n"
+"        Here you can decide which types of notifications you wish to "
+"receive, and it's frequency.<br />\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:14
+msgid ""
+"\n"
+"        Currently you have notifications enabled. You can always stop all "
+"notifications without loosing your settings and restart them afterwards.<br /"
+">\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:18
+msgid ""
+"\n"
+"        Currently you have notifications disabled. You can enable them "
+"clicking on the <strong>Start notifications</strong> button bellow.<br />\n"
+"        "
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:28
+msgid "Notify me when:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:32
+msgid "A new member joins"
+msgstr ""
+
+# must have extra space after in english
+#: forum/skins/default/templates/users/subscriptions.html:36
+#, fuzzy
+msgid "A new question is posted"
+msgstr "查看有关"
+
+#: forum/skins/default/templates/users/subscriptions.html:40
+msgid "A new question matching my interesting tags is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:44
+msgid "There's an update on one of my subscriptions"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:52
+msgid "Auto subscribe me to:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:57
+#, fuzzy
+msgid "Questions I ask"
+msgstr "您正在浏览的问题含有以下标签"
+
+#: forum/skins/default/templates/users/subscriptions.html:60
+#, fuzzy
+msgid "Questions I answer"
+msgstr "您正在浏览的问题含有以下标签"
+
+#: forum/skins/default/templates/users/subscriptions.html:63
+#, fuzzy
+msgid "Questions I comment"
+msgstr "问题列表"
+
+#: forum/skins/default/templates/users/subscriptions.html:68
+#, fuzzy
+msgid "Questions I view"
+msgstr "问题列表"
+
+#: forum/skins/default/templates/users/subscriptions.html:71
+msgid "All questions matching my interesting tags"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:82
+msgid "On my subscriptions, notify me when:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:87
+#, fuzzy
+msgid "An answer is posted"
+msgstr "受欢迎的提问"
+
+#: forum/skins/default/templates/users/subscriptions.html:90
+msgid "A comment on one of my posts is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:95
+msgid "A comment is posted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:98
+msgid "An answer is accepted"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:106
+msgid "More:"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:111
+msgid ""
+"Notify me when someone replys to one of my comments on any post using the "
+"<pre>@username</pre> notation"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:118
+msgid "Stop notifications"
+msgstr ""
+
+#: forum/skins/default/templates/users/subscriptions.html:120
+msgid "Start notifications"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:7
+msgid "User profile"
+msgstr "用户概览"
+
+#: forum/skins/default/templates/users/tabs.html:7
+msgid "overview"
+msgstr "概览"
+
+#: forum/skins/default/templates/users/tabs.html:9
+msgid "recent activity"
+msgstr "最近活动"
+
+#: forum/skins/default/templates/users/tabs.html:11
+msgid "graph of user reputation"
+msgstr "用户的社区积分历史"
+
+#: forum/skins/default/templates/users/tabs.html:12
+msgid "reputation history"
+msgstr "积分"
+
+#: forum/skins/default/templates/users/tabs.html:15 forum/views/users.py:196
+msgid "user vote record"
+msgstr "用户所有投票"
+
+#: forum/skins/default/templates/users/tabs.html:15
+msgid "casted votes"
+msgstr "投票"
+
+#: forum/skins/default/templates/users/tabs.html:18
+msgid "questions that user selected as his/her favorite"
+msgstr "用户收藏的问题"
+
+#: forum/skins/default/templates/users/tabs.html:19
+msgid "favorites"
+msgstr "收藏"
+
+#: forum/skins/default/templates/users/tabs.html:22
+msgid "email subscription settings"
+msgstr ""
+
+#: forum/skins/default/templates/users/tabs.html:23
+#, fuzzy
+msgid "subscriptions"
+msgstr "问题"
+
+#: forum/skins/default/templates/users/users.html:6
+#: forum/skins/default/templates/users/users.html:24
+msgid "Users"
+msgstr "用户列表"
+
+#: forum/skins/default/templates/users/users.html:27
+msgid "recent"
+msgstr "最新加入"
+
+#: forum/skins/default/templates/users/users.html:28
+msgid "oldest"
+msgstr "最先加入"
+
+#: forum/skins/default/templates/users/users.html:29
+msgid "by username"
+msgstr "用户名"
+
+#: forum/skins/default/templates/users/users.html:35
+#, fuzzy, python-format
+msgid "users matching query %(suser)s:"
+msgstr ""
+"匹配查询 '<span class=\"darkred\"><strong>%s</strong></span>' 的所有用户名:"
+
+#: forum/skins/default/templates/users/users.html:39
+msgid "Nothing found."
+msgstr "没有找到相关数据。"
+
+#: forum/templatetags/extra_tags.py:168 forum/templatetags/extra_tags.py:195
+#, fuzzy
+msgid "reputation points"
+msgstr "积分"
+
+#: forum/templatetags/extra_tags.py:248
+#, fuzzy
+msgid "2 days ago"
+msgstr "于%s<font class=\"darkred\">关闭</font>"
+
+#: forum/templatetags/extra_tags.py:250
+msgid "yesterday"
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:252
+#, python-format
+msgid "%(hr)d hour ago"
+msgid_plural "%(hr)d hours ago"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/templatetags/extra_tags.py:254
+#, python-format
+msgid "%(min)d min ago"
+msgid_plural "%(min)d mins ago"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/templatetags/node_tags.py:58
+msgid "permanent link"
+msgstr "永久链接"
+
+#: forum/templatetags/node_tags.py:58
+msgid "answer permanent link"
+msgstr "该回答的链接地址"
+
+#: forum/templatetags/node_tags.py:64
+#, fuzzy
+msgid "retag"
+msgstr "更新了标签"
+
+#: forum/templatetags/node_tags.py:68
+msgid "reopen"
+msgstr "打开"
+
+#: forum/templatetags/node_tags.py:70
+msgid "close"
+msgstr "关闭"
+
+#: forum/templatetags/node_tags.py:73 forum/views/commands.py:124
+#: forum/views/commands.py:136
+msgid "flag"
+msgstr ""
+
+#: forum/templatetags/node_tags.py:79
+msgid ""
+"report as offensive (i.e containing spam, advertising, malicious text, etc.)"
+msgstr "检举该帖为垃“水帖”(含广告、人身攻击、恶意言论等)"
+
+#: forum/templatetags/node_tags.py:82
+msgid "delete"
+msgstr "删除"
+
+#: forum/templatetags/question_list_tags.py:57
+#, fuzzy
+msgid "<strong>Newest</strong> questions are shown first. "
+msgstr "回复最多的问题将显示在最前面。"
+
+#: forum/templatetags/question_list_tags.py:58
+msgid "Questions are sorted by the <strong>time of last update</strong>."
+msgstr "问题按<strong>最后更新时间</strong>显示排序。"
+
+#: forum/templatetags/question_list_tags.py:59
+msgid "Questions sorted by <strong>number of responses</strong>."
+msgstr "问题按<strong>回复数量</strong>显示排序。"
+
+#: forum/templatetags/question_list_tags.py:60
+msgid "Questions are sorted by the <strong>number of votes</strong>."
+msgstr "问题按<strong>投票数量</strong>显示排序。"
+
+#: forum/templatetags/user_tags.py:58 forum/views/readers.py:293
+#, python-format
+msgid "Revision n. %(rev_number)d"
+msgstr ""
+
+#: forum/utils/forms.py:32
+#, fuzzy
+msgid "this field is required"
+msgstr " 标签不能为空。"
+
+#: forum/utils/forms.py:47
+msgid "choose a username"
+msgstr "选择一个用户名"
+
+#: forum/utils/forms.py:52
+#, fuzzy
+msgid "user name is required"
+msgstr " 标签不能为空。"
+
+#: forum/utils/forms.py:53
+#, fuzzy
+msgid "sorry, this name is taken, please choose another"
+msgstr "对不起,您不能注册该用户名,请换一个试试"
+
+#: forum/utils/forms.py:54
+#, fuzzy
+msgid "sorry, this name is not allowed, please choose another"
+msgstr "对不起,您不能注册该用户名,请换一个试试"
+
+#: forum/utils/forms.py:55
+msgid "sorry, there is no user with this name"
+msgstr ""
+
+#: forum/utils/forms.py:56
+msgid "sorry, we have a serious error - user name is taken by several users"
+msgstr ""
+
+#: forum/utils/forms.py:57
+msgid "user name can only consist of letters, empty space and underscore"
+msgstr ""
+
+#: forum/utils/forms.py:105
+msgid "your email address"
+msgstr "您的电子邮件地址"
+
+#: forum/utils/forms.py:106
+#, fuzzy
+msgid "email address is required"
+msgstr " 标签不能为空。"
+
+#: forum/utils/forms.py:108
+#, fuzzy
+msgid "this email is already used by someone else, please choose another"
+msgstr "该电子邮件已被注册,请选择另一个再试。"
+
+#: forum/utils/forms.py:133
+msgid "choose password"
+msgstr "密码"
+
+#: forum/utils/forms.py:134
+#, fuzzy
+msgid "password is required"
+msgstr " 标签不能为空。"
+
+#: forum/utils/forms.py:137
+msgid "retype password"
+msgstr "确认密码"
+
+#: forum/utils/forms.py:138
+#, fuzzy
+msgid "please, retype your password"
+msgstr "确认密码"
+
+#: forum/utils/forms.py:139
+msgid "sorry, entered passwords did not match, please try again"
+msgstr ""
+
+#: forum/views/admin.py:47
+#, python-format
+msgid "'%s' settings saved succesfully"
+msgstr ""
+
+#: forum/views/admin.py:141
+msgid "Bootstrap mode enabled"
+msgstr ""
+
+#: forum/views/admin.py:155
+msgid "All values reverted to defaults"
+msgstr ""
+
+#: forum/views/admin.py:171
+msgid "All values recalculated"
+msgstr ""
+
+#: forum/views/auth.py:103 forum/views/auth.py:112
+msgid ""
+"Sorry, these login credentials belong to anoother user. Plese terminate your "
+"current session and try again."
+msgstr ""
+
+#: forum/views/auth.py:105
+msgid "You are already logged in with that user."
+msgstr ""
+
+#: forum/views/auth.py:110
+msgid "These login credentials are already associated with your account."
+msgstr ""
+
+#: forum/views/auth.py:116
+msgid "The new credentials are now associated with your account"
+msgstr ""
+
+#: forum/views/auth.py:157
+msgid ""
+"Oops, something went wrong in the middle of this process. Please try again."
+msgstr ""
+
+#: forum/views/auth.py:219
+msgid "Temporary login link"
+msgstr ""
+
+#: forum/views/auth.py:224
+#, fuzzy
+msgid "An email has been sent with your temporary login key"
+msgstr "和您的邮件地址是绑定的"
+
+#: forum/views/auth.py:239
+msgid ""
+"You are logged in with a temporary access key, please take the time to fix "
+"your issue with authentication."
+msgstr ""
+
+#: forum/views/auth.py:245
+msgid "Email Validation"
+msgstr ""
+
+#: forum/views/auth.py:256
+msgid "Thank you, your email is now validated."
+msgstr ""
+
+#: forum/views/auth.py:280
+#, fuzzy
+msgid "Your password was changed"
+msgstr "密码"
+
+#: forum/views/auth.py:282
+#, fuzzy
+msgid "New password set"
+msgstr "密码"
+
+#: forum/views/auth.py:315
+#, python-format
+msgid "You removed the association with %s"
+msgstr ""
+
+#: forum/views/auth.py:353
+#, python-format
+msgid "Welcome back %s, you are now logged in"
+msgstr ""
+
+#: forum/views/commands.py:20
+#, python-format
+msgid ""
+"\n"
+"            Sorry, but you don't have enough reputation points to %(action)s."
+"<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:29
+#, python-format
+msgid ""
+"\n"
+"            Sorry but you cannot %(action)s your own post.<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:38
+#, python-format
+msgid ""
+"\n"
+"            Sorry but anonymous users cannot %(action)s.<br />\n"
+"            Please login or create an account <a href'%(signin_url)s'>here</"
+"a>.\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:47
+#, python-format
+msgid ""
+"\n"
+"            Sorry, but you don't have enough %(action)s left for today..<br /"
+">\n"
+"            The limit is %(limit)s per day..<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:57
+#, python-format
+msgid ""
+"\n"
+"            Sorry, but you cannot %(action)s twice the same post.<br />\n"
+"            Please check the <a href'%(faq_url)s'>faq</a>\n"
+"            "
+msgstr ""
+
+#: forum/views/commands.py:71 forum/views/commands.py:74
+#: forum/views/commands.py:111
+#, fuzzy
+msgid "vote"
+msgid_plural "votes"
+msgstr[0] "票"
+msgstr[1] "票"
+
+#: forum/views/commands.py:89
+#, python-format
+msgid ""
+"Sorry but you cannot cancel a vote after %(ndays)d %(tdays)s from the "
+"original vote"
+msgstr ""
+
+#: forum/views/commands.py:90
+msgid "day"
+msgid_plural "days"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/views/commands.py:110
+#, python-format
+msgid "You have %(nvotes)s %(tvotes)s left today."
+msgstr ""
+
+#: forum/views/commands.py:121 forum/views/commands.py:127
+msgid "flag posts"
+msgstr ""
+
+#: forum/views/commands.py:132
+#, fuzzy
+msgid "flags"
+msgstr "标签"
+
+#: forum/views/commands.py:149 forum/views/commands.py:155
+#, fuzzy
+msgid "like comments"
+msgstr "评论"
+
+#: forum/views/commands.py:152
+#, fuzzy
+msgid "like"
+msgstr "链接"
+
+#: forum/views/commands.py:179 forum/views/commands.py:182
+#, fuzzy
+msgid "delete comments"
+msgstr "删除任何一个评论"
+
+#: forum/views/commands.py:197
+#, fuzzy
+msgid "mark a question as favorite"
+msgstr "这个问题被"
+
+#: forum/views/commands.py:221 forum/views/commands.py:233
+#, fuzzy
+msgid "comment"
+msgstr "评论"
+
+#: forum/views/commands.py:224 forum/views/commands.py:351
+msgid "Invalid request"
+msgstr ""
+
+# todo - check if it's indeed plural
+#: forum/views/commands.py:230
+#, fuzzy
+msgid "edit comments"
+msgstr "添加评论"
+
+#: forum/views/commands.py:240
+msgid "Comment is empty"
+msgstr ""
+
+#: forum/views/commands.py:265
+#, fuzzy
+msgid "accept answers"
+msgstr "最先回答"
+
+#: forum/views/commands.py:271
+msgid "Sorry but only the question author can accept an answer"
+msgstr ""
+
+#: forum/views/commands.py:295 forum/views/commands.py:298
+#, fuzzy
+msgid "delete posts"
+msgstr "删除"
+
+#: forum/views/meta.py:43
+#, python-format
+msgid "Feedback message from %(site_name)s"
+msgstr ""
+
+#: forum/views/meta.py:46
+msgid "Thanks for the feedback!"
+msgstr ""
+
+#: forum/views/meta.py:53
+msgid "We look forward to hearing your feedback! Please, give it next time :)"
+msgstr ""
+
+#: forum/views/readers.py:64
+#, fuzzy
+msgid "Open questions without an accepted answer"
+msgstr "您正在浏览的问题含有以下标签"
+
+#: forum/views/readers.py:73
+#, python-format
+msgid "Questions tagged <span class=\"tag\">%(tag)s</span>"
+msgstr ""
+
+#: forum/views/readers.py:131
+#, python-format
+msgid "questions matching '%(keywords)s'"
+msgstr ""
+
+#: forum/views/users.py:152
+#, fuzzy
+msgid "user profile"
+msgstr "用户概览"
+
+#: forum/views/users.py:152
+#, fuzzy
+msgid "user profile overview"
+msgstr "用户概览"
+
+#: forum/views/users.py:186
+#, fuzzy
+msgid "recent user activity"
+msgstr "最近活动"
+
+#: forum/views/users.py:186
+#, fuzzy
+msgid "profile - recent activity"
+msgstr "最近活动"
+
+#: forum/views/users.py:196
+msgid "profile - votes"
+msgstr "投票 - 用户资料"
+
+#: forum/views/users.py:203
+msgid "user reputation in the community"
+msgstr "用户社区积分"
+
+#: forum/views/users.py:203
+msgid "profile - user reputation"
+msgstr "积分 - 用户资料"
+
+#: forum/views/users.py:214
+#, fuzzy
+msgid "favorite questions"
+msgstr "收藏"
+
+#: forum/views/users.py:214
+msgid "profile - favorite questions"
+msgstr "收藏 - 用户资料"
+
+#: forum/views/users.py:220
+#, fuzzy
+msgid "subscription settings"
+msgstr "用户参数的设置"
+
+#: forum/views/users.py:220
+#, fuzzy
+msgid "profile - subscriptions"
+msgstr "积分 - 用户资料"
+
+#: forum/views/users.py:230
+msgid "Notifications are now enabled"
+msgstr ""
+
+#: forum/views/users.py:232
+msgid "Notifications are now disabled"
+msgstr ""
+
+#: forum/views/users.py:239
+msgid "New subscription settings are now saved"
+msgstr ""
+
+#: forum/views/writers.py:68
+msgid "uploading images is limited to users with >60 reputation points"
+msgstr "上传图片只限于积分+60以上注册用户!"
+
+# todo take these out of settings
+#: forum/views/writers.py:70
+msgid "allowed file types are 'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'"
+msgstr "只允许上传'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'类型的文件!"
+
+#: forum/views/writers.py:72
+#, fuzzy, python-format
+msgid "maximum upload file size is %sM"
+msgstr "只允许上传%sK大小的文件!"
+
+#: forum/views/writers.py:74
+#, fuzzy, python-format
+msgid ""
+"Error uploading file. Please contact the site administrator. Thank you. %s"
+msgstr "在文件上传过程中产生了错误,请联系管理员,谢谢^_^"
+
+#: forum/views/writers.py:85
+#, fuzzy
+msgid "Initial revision"
+msgstr "初始版本"
+
+#: forum/views/writers.py:143
+#, fuzzy
+msgid "Retag"
+msgstr "标签"
+
+#: forum_modules/books/urls.py:7 forum_modules/books/urls.py:8
+#: forum_modules/books/urls.py:9
+#, fuzzy
+msgid "books/"
+msgstr "读书"
+
+#: forum_modules/default_badges/badges.py:17
+#: forum_modules/default_badges/badges.py:24
+#: forum_modules/default_badges/badges.py:31
+#, fuzzy, python-format
+msgid "Asked a question with %s views"
+msgstr "我要提问"
+
+#: forum_modules/default_badges/badges.py:39
+#: forum_modules/default_badges/badges.py:53
+#: forum_modules/default_badges/badges.py:67
+#, fuzzy, python-format
+msgid "Answer voted up %s times"
+msgstr "该用户投的赞成票总数"
+
+#: forum_modules/default_badges/badges.py:46
+#: forum_modules/default_badges/badges.py:60
+#: forum_modules/default_badges/badges.py:74
+#, fuzzy, python-format
+msgid "Question voted up %s times"
+msgstr "该用户投的赞成票总数"
+
+#: forum_modules/default_badges/badges.py:82
+#: forum_modules/default_badges/badges.py:89
+#, fuzzy, python-format
+msgid "Question favorited by %s users"
+msgstr "您正在浏览的问题含有以下标签"
+
+#: forum_modules/default_badges/badges.py:97
+#, python-format
+msgid "Deleted own post with score of %s or higher"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:108
+#, python-format
+msgid "Deleted own post with score of %s or lower"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:120
+msgid "First flagged post"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:127
+#, fuzzy
+msgid "First down vote"
+msgstr "投反对票"
+
+#: forum_modules/default_badges/badges.py:134
+msgid "First retag"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:141
+#, fuzzy
+msgid "First up vote"
+msgstr "投赞成票"
+
+#: forum_modules/default_badges/badges.py:148
+msgid "First edit"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:155
+#, fuzzy
+msgid "First accepted answer on your own question"
+msgstr "不是一个可以回答的“问题”"
+
+#: forum_modules/default_badges/badges.py:162
+#, fuzzy
+msgid "Completed all user profile fields"
+msgstr "完成个人所有资料"
+
+#: forum_modules/default_badges/badges.py:169
+msgid "First rollback"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:177
+#, python-format
+msgid "Voted %s times"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:184
+#, fuzzy, python-format
+msgid "Left %s comments"
+msgstr "评论"
+
+#: forum_modules/default_badges/badges.py:192
+#, python-format
+msgid "Answered your own question with at least %s up votes"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:205
+msgid "Strunk & White"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:206
+#, fuzzy, python-format
+msgid "Edited %s entries"
+msgstr "修改回答"
+
+#: forum_modules/default_badges/badges.py:217
+msgid "Asked first question with at least one up vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:228
+msgid "Answered first question with at least one up vote"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:260
+#, python-format
+msgid "First answer was accepted with at least %s up votes"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:271
+#, fuzzy, python-format
+msgid "Accepted answer and voted up %s times"
+msgstr "该回答总共有%d个投票"
+
+#: forum_modules/default_badges/badges.py:282
+#, python-format
+msgid ""
+"Answered a question more than %(dif_days)s days later with at least %"
+"(up_votes)s votes"
+msgstr ""
+
+#: forum_modules/default_badges/badges.py:295
+#, fuzzy, python-format
+msgid "Created a tag used by %s questions"
+msgstr "最新问题"
+
+#: forum_modules/default_badges/settings.py:6
+msgid "Popular Question views"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:7
+msgid ""
+"\n"
+"Number of question views required to award a Popular Question badge to the "
+"question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:12
+#, fuzzy
+msgid "Notable Question views"
+msgstr "全部问题"
+
+#: forum_modules/default_badges/settings.py:13
+msgid ""
+"\n"
+"Number of question views required to award a Notable Question badge to the "
+"question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:18
+#, fuzzy
+msgid "Famous Question views"
+msgstr "问题列表"
+
+#: forum_modules/default_badges/settings.py:19
+msgid ""
+"\n"
+"Number of question views required to award a Famous Question badge to the "
+"question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:24
+#, fuzzy
+msgid "Nice Answer up votes"
+msgstr "当前总票数"
+
+#: forum_modules/default_badges/settings.py:25
+msgid ""
+"\n"
+"Number of up votes required to award a Nice Answer badge to the answer "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:30
+#, fuzzy
+msgid "Nice Question up votes"
+msgstr "您正在浏览的问题含有以下标签"
+
+#: forum_modules/default_badges/settings.py:31
+msgid ""
+"\n"
+"Number of up votes required to award a Nice Question badge to the question "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:36
+#, fuzzy
+msgid "Good Answer up votes"
+msgstr "今日剩余投票数"
+
+#: forum_modules/default_badges/settings.py:37
+msgid ""
+"\n"
+"Number of up votes required to award a Good Answer badge to the answer "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:42
+#, fuzzy
+msgid "Good Question up votes"
+msgstr "您正在浏览的问题含有以下标签"
+
+#: forum_modules/default_badges/settings.py:43
+msgid ""
+"\n"
+"Number of up votes required to award a Good Question badge to the question "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:48
+#, fuzzy
+msgid "Great Answer up votes"
+msgstr "当前总票数"
+
+#: forum_modules/default_badges/settings.py:49
+msgid ""
+"\n"
+"Number of up votes required to award a Great Answer badge to the answer "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:54
+#, fuzzy
+msgid "Great Question up votes"
+msgstr "给任何问题整理标签"
+
+#: forum_modules/default_badges/settings.py:55
+msgid ""
+"\n"
+"Number of up votes required to award a Great Question badge to the question "
+"author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:60
+#, fuzzy
+msgid "Favorite Question favorite count"
+msgstr "收藏"
+
+#: forum_modules/default_badges/settings.py:61
+msgid ""
+"\n"
+"How many times a question needs to be favorited by other users to award a "
+"Favorite Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:66
+msgid "Stellar Question favorite count"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:67
+msgid ""
+"\n"
+"How many times a question needs to be favorited by other users to award a "
+"Stellar Question badge to the question author\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:72
+msgid "Disciplined minimum score"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:73
+msgid ""
+"\n"
+"Minimum score a question needs to have to award the Disciplined badge to an "
+"author of a question who deletes it.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:78
+msgid "Peer Pressure maximum score"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:79
+msgid ""
+"\n"
+"Maximum score a question needs to have to award the Peer Pressure badge to "
+"an author of a question who deletes it.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:84
+msgid "Civic Duty votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:85
+msgid ""
+"\n"
+"Number of votes an user needs to cast to be awarded the Civic Duty badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:90
+#, fuzzy
+msgid "Pundit number of comments"
+msgstr "当前总票数"
+
+#: forum_modules/default_badges/settings.py:91
+msgid ""
+"\n"
+"Number of comments an user needs to post to be awarded the Pundit badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:96
+msgid "Self Learner up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:97
+msgid ""
+"\n"
+"Number of up votes an answer from the question author needs to have for the "
+"author to be awarded the Self Learner badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:102
+msgid "Strunk and White updates"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:103
+msgid ""
+"\n"
+"Number of question or answer updates an user needs to make to be awarded the "
+"Strunk & White badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:108
+msgid "Enlightened up votes"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:109
+msgid ""
+"\n"
+"Number of up votes an accepted answer needs to have for the author to be "
+"awarded the Enlightened badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:114
+#, fuzzy
+msgid "Guru up votes"
+msgstr "票数"
+
+#: forum_modules/default_badges/settings.py:115
+msgid ""
+"\n"
+"Number of up votes an accepted answer needs to have for the author to be "
+"awarded the Guru badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:120
+#, fuzzy
+msgid "Necromancer up votes"
+msgstr "撤销投票"
+
+#: forum_modules/default_badges/settings.py:121
+msgid ""
+"\n"
+"Number of up votes an answer needs to have for the author to be awarded the "
+"Necromancer badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:126
+msgid "Necromancer difference in days"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:127
+msgid ""
+"\n"
+"Difference in days betwen the posted date of a question and an answer for "
+"the answer author to be awarded the Necromancer badge.\n"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:132
+msgid "Taxonomist usage count"
+msgstr ""
+
+#: forum_modules/default_badges/settings.py:133
+msgid ""
+"\n"
+"How many usages a tag needs to have for the tag creator to be awarded the "
+"Taxonomist badge. \n"
+msgstr ""
+
+#: forum_modules/facebookauth/authentication.py:31
+msgid "Sorry, your Facebook session has expired, please try again"
+msgstr ""
+
+#: forum_modules/facebookauth/authentication.py:33
+msgid ""
+"The authentication with Facebook connect failed due to an invalid signature"
+msgstr ""
+
+#: forum_modules/facebookauth/authentication.py:35
+msgid ""
+"The authentication with Facebook connect failed, cannot find authentication "
+"tokens"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:75
+msgid "Please enter valid username and password (both are case-sensitive)."
+msgstr ""
+
+#: forum_modules/localauth/forms.py:79
+msgid "This account is inactive."
+msgstr ""
+
+#: forum_modules/localauth/forms.py:81
+#, fuzzy
+msgid "Login failed."
+msgstr "用户名"
+
+#: forum_modules/localauth/forms.py:85
+msgid "This user is not a valid user"
+msgstr ""
+
+#: forum_modules/localauth/forms.py:88
+#, fuzzy
+msgid "Please enter username and password"
+msgstr "使用帐号密码登录"
+
+#: forum_modules/localauth/forms.py:90
+#, fuzzy
+msgid "Please enter your password"
+msgstr "重设密码"
+
+#: forum_modules/localauth/forms.py:92
+#, fuzzy
+msgid "Please enter user name"
+msgstr "请帮助我们回答"
+
+#: forum_modules/localauth/urls.py:7
+msgid "local/"
+msgstr ""
+
+#: forum_modules/localauth/views.py:33
+#, fuzzy
+msgid "A validation email has been sent to your email address. "
+msgstr "和您的邮件地址是绑定的"
+
+#: forum_modules/oauthauth/consumer.py:33
+msgid "Error, the oauth token is not on the server"
+msgstr ""
+
+#: forum_modules/oauthauth/consumer.py:38
+msgid "Something went wrong! Auth tokens do not match"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:40
+msgid "Sorry, but your input is not a valid OpenId"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:92
+msgid "The OpenId authentication request was canceled"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:94
+msgid "The OpenId authentication failed: "
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:96
+msgid "Setup needed"
+msgstr ""
+
+#: forum_modules/openidauth/consumer.py:98
+msgid "The OpenId authentication failed with an unknown status: "
+msgstr ""
+
+#: forum_modules/openidauth/templates/openidurl.html:7
+#, fuzzy
+msgid "Enter your OpenId Url"
+msgstr "使用OpenID注册"
+
+#: forum_modules/project_badges/badges.py:9
+#, python-format
+msgid "Got %s upvotes in a question tagged with \"bug\""
+msgstr ""
+
+#: forum_modules/recaptcha/formfield.py:20
+msgid "Invalid captcha"
+msgstr ""
+
+#: forum_modules/sximporter/importer.py:39
+#, python-format
+msgid "Unknown user %(number)d"
+msgstr ""
+
+#: forum_modules/sximporter/urls.py:8
+msgid "sximporter/"
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:7
+msgid "SX Importer"
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:10
+msgid "Welcome to Stack Exchange dump importer."
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:16
+msgid "Your user id in stack exchange"
+msgstr ""
+
+#: forum_modules/sximporter/templates/page.html:20
+msgid "Merge users with same user name and email"
+msgstr ""
+
+#: locale/phrases.py:1
+msgid "Test Phrase 1"
+msgstr ""
+
+#: locale/phrases.py:2
+msgid "Test Phrase 2"
+msgstr ""
+
+#: locale/phrases.py:3
+msgid "Test Phrase 3"
+msgstr ""
+
+#: locale/phrases.py:4
+msgid "Test Phrase n"
+msgstr ""
+
+#, fuzzy
+#~ msgid "i-names are not supported"
+#~ msgstr "基本的HTML标签也是支持的"
+
+# translation and user name validation are language-specific
+#~ msgid "invalid user name"
+#~ msgstr "用户名只能包含英文字母、数字和下划线"
+
+# minimal length of user name may be language specific
+#~ msgid "username too short"
+#~ msgstr "用户名太短,请使用三个或三个以上字符"
+
+#~ msgid "this name is already in use - please try anoter"
+#~ msgstr "该用户名已被注册,请换一个试试"
+
+#~ msgid ""
+#~ "This email is already                 registered in our database. Please "
+#~ "choose another."
+#~ msgstr "该电子邮件已被注册,请选择另一个再试。"
+
+#~ msgid "Incorrect username."
+#~ msgstr "选择一个用户名"
+
+#, fuzzy
+#~ msgid "signup/"
+#~ msgstr "注册帐号"
+
+# todo please check this in chinese
+#, fuzzy
+#~ msgid "Account deleted."
+#~ msgstr "取消"
+
+#, fuzzy
+#~ msgid "Request for new password"
+#~ msgstr "重设密码"
+
+#~ msgid "site title"
+#~ msgstr "CNProg.com"
+
+#~ msgid "site slogan"
+#~ msgstr "程序员问答社区"
+
+#~ msgid "meta site content"
+#~ msgstr ""
+#~ "中国程序员的编程技术问答社区。我们做专业的、可协作编辑的技术问答社区。"
+
+#~ msgid ""
+#~ "please use space to separate tags (this enables autocomplete feature)"
+#~ msgstr "多个标签请用空格间隔-最多5个标签。(优先使用自动匹配的英文标签。)"
+
+#~ msgid "responses"
+#~ msgstr "回应"
+
+#~ msgid "profile - responses"
+#~ msgstr "回应 - 用户资料"
+
+#~ msgid "users favorite questions"
+#~ msgstr "用户收藏的问题"
+
+#~ msgid "preferences"
+#~ msgstr "设置"
+
+#~ msgid "profile - user preferences"
+#~ msgstr "设置 - 用户资料"
+
+#, fuzzy
+#~ msgid " ago"
+#~ msgstr "前"
+
+#~ msgid "Save"
+#~ msgstr "保存"
+
+#~ msgid "learn more about OpenID"
+#~ msgstr "了解更多有关OpenID的信息"
+
+#~ msgid "User name"
+#~ msgstr "您的大名"
+
+#~ msgid "Email: (won't be shown to anyone)"
+#~ msgstr "电子邮件:(不会公开显示)"
+
+#~ msgid ""
+#~ "gold badge descriptionGold 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 ""
+#~ "金牌是十分罕见的。你不仅要参与社区的提问、回答、投票等活动,而且需要有高深"
+#~ "的知识和能力才能获得。"
+
+#~ msgid ""
+#~ "silver badge descriptionObtaining silver badge requires significant "
+#~ "patience. If you got one, you've very significantly contributed to this "
+#~ "community"
+#~ msgstr "它是不同寻常的荣誉,只要你付出足够的努力就会得到。"
+
+#~ msgid "Connect with Twitter"
+#~ msgstr "同步Twitter消息"
+
+#~ msgid "Twitter account name:"
+#~ msgstr "账号:"
+
+#~ msgid "Twitter password:"
+#~ msgstr "密码:"
+
+#~ msgid "Send my Questions to Twitter"
+#~ msgstr "发布我的提问到我的Twitter"
+
+#~ msgid "Send my Answers to Twitter"
+#~ msgstr "发布我的回答到我的Twitter"
+
+#, fuzzy
+#~ msgid ""
+#~ "bronze badge descriptionIf you are active in this community, you will get "
+#~ "this medal - still it is a special honor."
+#~ msgstr "铜牌会在你活跃于社区时产生,它相对容易获得,但也是一种特殊的荣誉。"
+
+# base_content.html
+#~ msgid "congratulations, community gave you a badge"
+#~ msgstr "恭喜您,社区给您颁发了奖牌"
+
+#~ msgid "see"
+#~ msgstr "查看"
+
+#, fuzzy
+#~ msgid "About us"
+#~ msgstr "关于本站"
+
+#, fuzzy
+#~ msgid "Contact"
+#~ msgstr "联系我们"
+
+#~ msgid "my profile"
+#~ msgstr "我的资料"
+
+#~ msgid "last updated questions"
+#~ msgstr "最新更新的问题"
+
+#~ msgid "given to"
+#~ msgstr "授予"
+
+#~ msgid "subscribe to last 30 questions by RSS"
+#~ msgstr "RSS订阅最新30个问题"
+
+#~ msgid "Still looking for more? See"
+#~ msgstr "在寻找更多问题吗?请查阅"
+
+#, fuzzy
+#~ msgid "complete list of quesionts"
+#~ msgstr "全部问题列表"
+
+#, fuzzy
+#~ msgid "Size per page:"
+#~ msgstr "每页显示"
+
+#~ msgid ""
+#~ "remove favorite mark from this question (click again to restore mark)"
+#~ msgstr "我要收藏这个问题(再次点击取消操作)"
+
+#~ msgid "flag offensive"
+#~ msgstr "垃圾帖?"
+
+#~ msgid "Answers"
+#~ msgstr "个回答"
+
+#~ msgid "i like this answer (click again to cancel)"
+#~ msgstr "这篇帖子有价值(再次点击取消操作)"
+
+#~ msgid "i dont like this answer (click again to cancel)"
+#~ msgstr "这篇帖子没有价值(再次点击取消操作)"
+
+#~ msgid "mark this answer as favorite (click again to undo)"
+#~ msgstr "最佳答案(再次点击取消操作)"
+
+# todo please check this in chinese
+#~ msgid "undelete"
+#~ msgstr "取消"
+
+#~ msgid "Login to answer"
+#~ msgstr "登录并回答该问题"
+
+#~ msgid "ago"
+#~ msgstr "前"
+
+#, fuzzy
+#~ msgid "please ask a relevant question"
+#~ msgstr "我要提问"
+
+# index.html
+#~ msgid "Community wiki"
+#~ msgstr "社区Wiki"
+
+# must have extra space after in english
+#, fuzzy
+#~ msgid "Browse questions with tag of "
+#~ msgstr "查看有关"
+
+#~ msgid "have %(num_q)s unanswered questions"
+#~ msgstr ""
+#~ "您正在浏览所有<br><div class=\"questions-count\">%(num_q)s</div>个<p>问题"
+#~ "按 <strong>问题创建时间</strong> 排序。最新加入的问题将显示在最前面。</p>"
+
+# in unanswered.html and somewhere else
+#~ msgid "Have a total of"
+#~ msgstr "您正在浏览所有"
+
+#~ msgid "avatar"
+#~ msgstr "修改头像"
+
+#~ msgid "User questions"
+#~ msgstr "个问题"
+
+#, fuzzy
+#~ msgid ""
+#~ "the answer has been commented %(answered_question.comment_count)s times"
+#~ msgstr "该回答有%d条评论"
+
+#~ msgid "votes total"
+#~ msgstr "个投票"
+
+#~ msgid "Tags"
+#~ msgstr "个标签"
+
+#, fuzzy
+#~ msgid "this questions was selected as favorite"
+#~ msgstr "这个问题被"
+
+#~ msgid "Change email"
+#~ msgstr "更换电子邮件"
+
+#, fuzzy
+#~ msgid "Account: change OpenID URL"
+#~ msgstr "更换OpenID地址"
+
+#, fuzzy
+#~ msgid "Account: change password"
+#~ msgstr "修改密码"
+
+#, fuzzy
+#~ msgid "New password again"
+#~ msgstr "发送新密码"
+
+#, fuzzy
+#~ msgid ""
+#~ "Your OpenID is accepted. Please complete this to finish registration."
+#~ msgstr "您的OpenID帐号已经验证通过! 请完成最后一步 - 绑定OpenID到您的帐号。"
+
+#~ msgid "New account"
+#~ msgstr "新帐号"
+
+#~ msgid "User name (<i>will be shown to others, cannot be modified</i>)"
+#~ msgstr "用户名(<i>在社区显示友好名称,不可更改</i>)"
+
+#, fuzzy
+#~ msgid "Password:"
+#~ msgstr "密码"
+
+#, fuzzy
+#~ msgid "Delete account permanently"
+#~ msgstr "删除帐号"
+
+#~ msgid "Send new password"
+#~ msgstr "发送新密码"
+
+#~ msgid "Lost your password? No problem - here you can reset it."
+#~ msgstr "丢失了您的密码? 你可以在这里重设密码。"
+
+#~ msgid ""
+#~ "Please enter your username below and new password will be sent to your "
+#~ "registered e-mail"
+#~ msgstr "请输入用户名,新的密码会发送到你注册时候填写的电子邮件。"
+
+# todo - check translation or see if it's indeed true
+#~ msgid ""
+#~ "Note: your new password will be activated only after you click the "
+#~ "activation link in the email message"
+#~ msgstr "注意: 新的密码只有您在激活邮件中的链接后才会被激活。"
+
+#~ msgid "we support two login modes"
+#~ msgstr ""
+#~ "CNProg支持<b>两种</b>登录模式。您可以使用帐号、密码登录,或者使用OpenID登"
+#~ "录。"
+
+#~ msgid "Login with your OpenID"
+#~ msgstr "使用OpenID登录"
+
+#~ msgid "select openid provider"
+#~ msgstr "1)请选择您的帐号类:"
+
+#~ msgid "verify openid link and login"
+#~ msgstr "2)型并完成正确的OpenID地址(如:替换“{username}”为您的对应帐号):"
+
+#, fuzzy
+#~ msgid "Create new acccount"
+#~ msgstr "注册新帐号"
+
+#~ msgid ""
+#~ "We support two types of user registration: conventional username/"
+#~ "password, and"
+#~ msgstr "我们支持两种注册方式,你可以使用常规的用户名、密码方式注册,或者"
+
+#~ msgid "the OpenID method"
+#~ msgstr "使用OpenID帐号注册"
+
+#, fuzzy
+#~ msgid "Sorry, looks like we have some errors"
+#~ msgstr "请注意以下错误:"
+
+#~ msgid "Conventional registration"
+#~ msgstr "请注意以下错误:"
+
+#~ msgid "choose a user name"
+#~ msgstr "选择一个用户名"
+
+#~ msgid "back to login"
+#~ msgstr "返回登录"
+
+#~ msgid "meta site keywords, comma separated"
+#~ msgstr ""
+#~ "技术问答社区,中国程序员,编程技术社区,程序员社区,程序员论坛,程序员"
+#~ "wiki,程序员博客"
+
+#~ msgid "what is this website"
+#~ msgstr ""
+#~ "CNProg是一个<strong>面向程序员</strong>的可协作编辑的<strong>开放源代码问"
+#~ "答社区</strong>。"
+
+#~ msgid "what can one do on this website"
+#~ msgstr ""
+#~ "您可以在这里提问各类<strong>程序技术问题</strong> - 问题不分语言和平台。 "
+#~ "同时也希望您对力所能及的问题,给予您的宝贵答案。"
+
+#~ msgid "book technical Q&A"
+#~ msgstr "图书相关的技术答疑"
+
+#~ msgid "blog"
+#~ msgstr "Blog"
+
+#~ msgid "current revision"
+#~ msgstr "当前版本"
+
+#~ msgid "Change now"
+#~ msgstr "现在修改"
+
+#~ msgid "uses tags for the classification of questions"
+#~ msgstr "用标签来分类系统的信息"
+
+#~ msgid "Found by tag"
+#~ msgstr "标签问题"
+
+#~ 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 "Most recently answered ones are shown first."
+#~ msgstr "最后被回答或者>更新的问题将显示在最前面。"
+
+#~ msgid "Most voted questions are shown first"
+#~ 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 "gold badge: the highest honor and is very rare"
+#~ msgstr "金牌:十分罕见之最高荣耀"
+
+#~ msgid ""
+#~ "silver badge: occasionally awarded for the very high quality contributions"
+#~ msgstr "银牌:偶尔颁发之优质奖章"
+
+#~ msgid "Gold badge is very rare."
+#~ msgstr "金牌是十分罕见的。"
+
+#~ msgid "Gold badge is the highest award in this community."
+#~ msgstr "获得金牌意味着你在某个层次上已经达到了顶峰。"
+
+#~ msgid "Obtaining silver badge requires significant patience."
+#~ msgstr "银牌需要经过长时间的奋斗才能获得。"
diff --git a/forum/modules/template_loader.py/log/README.TXT b/forum/modules/template_loader.py/log/README.TXT
new file mode 100644 (file)
index 0000000..54247a8
--- /dev/null
@@ -0,0 +1 @@
+this file is just a placeholder so the empty directory is not ignored by version control
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/manage.py b/forum/modules/template_loader.py/manage.py
new file mode 100644 (file)
index 0000000..f9894f5
--- /dev/null
@@ -0,0 +1,13 @@
+#!/usr/bin/env python
+from django.core.management import execute_manager
+try:
+    import settings # Assumed to be in the same directory.
+except ImportError, e:
+    import traceback
+    traceback.print_exc()
+    import sys
+    sys.stderr.write("Error: Can't find the file 'forms.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file forms.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
+    sys.exit(1)
+
+if __name__ == "__main__":
+    execute_manager(settings)
diff --git a/forum/modules/template_loader.py/osqa.iml b/forum/modules/template_loader.py/osqa.iml
new file mode 100644 (file)
index 0000000..aa15d10
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<module type="PYTHON_MODULE" version="4">\r
+  <component name="FacetManager">\r
+    <facet type="django" name="Django">\r
+      <configuration>\r
+        <option name="rootFolder" value="$MODULE_DIR$" />\r
+        <option name="templatesFolder" value="$MODULE_DIR$/forum/skins/default/templates" />\r
+        <option name="settingsModule" value="settings.py" />\r
+      </configuration>\r
+    </facet>\r
+  </component>\r
+  <component name="NewModuleRootManager" inherit-compiler-output="false">\r
+    <content url="file://$MODULE_DIR$" />\r
+    <orderEntry type="inheritedJdk" />\r
+    <orderEntry type="sourceFolder" forTests="false" />\r
+  </component>\r
+</module>\r
+\r
diff --git a/forum/modules/template_loader.py/osqa.wsgi.dist b/forum/modules/template_loader.py/osqa.wsgi.dist
new file mode 100644 (file)
index 0000000..70c0da8
--- /dev/null
@@ -0,0 +1,11 @@
+import os
+import sys
+sys.path.append('/path/to_dir_above')
+sys.path.append('/path/to_dir_above/osqa')
+# The first part of this module name should be identical to the directory name
+# of the OSQA source.  For instance, if the full path to OSQA is
+# /home/osqa/osqa-server, then the DJANGO_SETTINGS_MODULE should have a value
+# of 'osqa-server.settings'.
+os.environ['DJANGO_SETTINGS_MODULE'] = 'osqa.settings'
+import django.core.handlers.wsgi
+application = django.core.handlers.wsgi.WSGIHandler()
diff --git a/forum/modules/template_loader.py/rmpyc b/forum/modules/template_loader.py/rmpyc
new file mode 100644 (file)
index 0000000..014575f
--- /dev/null
@@ -0,0 +1 @@
+rm `find . -name '*.pyc'`
diff --git a/forum/modules/template_loader.py/settings.py b/forum/modules/template_loader.py/settings.py
new file mode 100644 (file)
index 0000000..bd76b22
--- /dev/null
@@ -0,0 +1,115 @@
+# encoding:utf-8
+# Django settings for lanai project.
+import os.path
+import sys
+
+SITE_ID = 1
+
+ADMIN_MEDIA_PREFIX = '/admin_media/'
+SECRET_KEY = '$oo^&_m&qwbib=(_4m_n*zn-d=g#s0he5fx9xonnym#8p6yigm'
+# List of callables that know how to import templates from various sources.
+TEMPLATE_LOADERS = (
+    'django.template.loaders.filesystem.load_template_source',
+    'django.template.loaders.app_directories.load_template_source',
+    'forum.modules.module_templates_loader',
+    'forum.skins.load_template_source',
+#     'django.template.loaders.eggs.load_template_source',
+)
+
+MIDDLEWARE_CLASSES = [
+    #'django.middleware.gzip.GZipMiddleware',
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    #'django.middleware.locale.LocaleMiddleware',
+    #'django.middleware.cache.UpdateCacheMiddleware',
+    'django.middleware.common.CommonMiddleware',
+    #'django.middleware.cache.FetchFromCacheMiddleware',
+    'forum.middleware.extended_user.ExtendedUser',
+    #'django.middleware.sqlprint.SqlPrintingMiddleware',
+    'forum.middleware.anon_user.ConnectToSessionMessagesMiddleware',
+    'forum.middleware.request_utils.RequestUtils',
+    'forum.middleware.cancel.CancelActionMiddleware',
+    #'recaptcha_django.middleware.ReCaptchaMiddleware',
+    'django.middleware.transaction.TransactionMiddleware',
+]
+
+TEMPLATE_CONTEXT_PROCESSORS = (
+    'django.core.context_processors.request',
+    'forum.context.application_settings',
+    #'django.core.context_processors.i18n',
+    'forum.user_messages.context_processors.user_messages',#must be before auth
+    'django.core.context_processors.auth', #this is required for admin
+)
+
+ROOT_URLCONF = 'urls'
+
+TEMPLATE_DIRS = (
+    os.path.join(os.path.dirname(__file__),'forum','skins').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",)
+DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage'
+# for user upload
+ALLOW_FILE_TYPES = ('.jpg', '.jpeg', '.gif', '.bmp', '.png', '.tiff')
+# unit byte
+ALLOW_MAX_FILE_SIZE = 1024 * 1024
+
+# User settings
+from settings_local import *
+
+try:
+    if len(FORUM_SCRIPT_ALIAS) > 0:
+        APP_URL = '%s/%s' % (APP_URL, FORUM_SCRIPT_ALIAS[:-1])
+except NameError:
+    pass
+
+app_url_split = APP_URL.split("://")
+
+APP_PROTOCOL = app_url_split[0]
+APP_DOMAIN = app_url_split[1].split('/')[0]
+APP_BASE_URL = '%s://%s' % (APP_PROTOCOL, APP_DOMAIN)
+
+FORCE_SCRIPT_NAME = ''
+
+for path in app_url_split[1].split('/')[1:]:
+    FORCE_SCRIPT_NAME = FORCE_SCRIPT_NAME + '/' + path
+
+if FORCE_SCRIPT_NAME.endswith('/'):
+    FORCE_SCRIPT_NAME = FORCE_SCRIPT_NAME[:-1]
+
+INSTALLED_APPS = [
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.sites',
+    'django.contrib.admin',
+    'django.contrib.humanize',
+    'django.contrib.sitemaps',
+    'django.contrib.markup',
+    'forum',
+]
+
+if DEBUG:
+    try:
+        import debug_toolbar
+        MIDDLEWARE_CLASSES.append('debug_toolbar.middleware.DebugToolbarMiddleware')
+        INSTALLED_APPS.append('debug_toolbar')
+    except:
+        pass
+
+try:
+    import south
+    INSTALLED_APPS.append('south')
+except:
+    pass
+
+if not DEBUG:
+    try:
+        import rosetta
+        INSTALLED_APPS.append('rosetta')
+    except:
+        pass
+
+AUTHENTICATION_BACKENDS = ['django.contrib.auth.backends.ModelBackend',]
diff --git a/forum/modules/template_loader.py/settings_local.py.dist b/forum/modules/template_loader.py/settings_local.py.dist
new file mode 100644 (file)
index 0000000..9768cfa
--- /dev/null
@@ -0,0 +1,54 @@
+# encoding:utf-8
+import os.path
+
+SITE_SRC_ROOT = os.path.dirname(__file__)
+LOG_FILENAME = 'django.osqa.log'
+
+#for logging
+import logging
+logging.basicConfig(
+    filename=os.path.join(SITE_SRC_ROOT, 'log', LOG_FILENAME),
+    level=logging.ERROR,
+    format='%(pathname)s TIME: %(asctime)s MSG: %(filename)s:%(funcName)s:%(lineno)d %(message)s',
+)
+
+#ADMINS and MANAGERS
+ADMINS = ()
+MANAGERS = ADMINS
+
+DEBUG = False
+DEBUG_TOOLBAR_CONFIG = {
+    'INTERCEPT_REDIRECTS': True
+}
+TEMPLATE_DEBUG = DEBUG
+INTERNAL_IPS = ('127.0.0.1',)
+
+
+DATABASE_NAME = ''             # Or path to database file if using sqlite3.
+DATABASE_USER = ''               # Not used with sqlite3.
+DATABASE_PASSWORD = ''               # Not used with sqlite3.
+DATABASE_ENGINE = ''  #mysql, etc
+DATABASE_HOST = ''
+DATABASE_PORT = ''
+
+CACHE_BACKEND = 'file://%s' % os.path.join(os.path.dirname(__file__),'cache').replace('\\','/')
+#CACHE_BACKEND = 'dummy://'
+SESSION_ENGINE = 'django.contrib.sessions.backends.db'
+
+# This should be equal to your domain name, plus the web application context.
+# This shouldn't be followed by a trailing slash.
+# I.e., http://www.yoursite.com or http://www.hostedsite.com/yourhostapp
+APP_URL = 'http://'
+
+#LOCALIZATIONS
+TIME_ZONE = 'America/New_York'
+
+#OTHER SETTINGS
+
+USE_I18N = True
+LANGUAGE_CODE = 'en'
+
+DJANGO_VERSION = 1.1
+OSQA_DEFAULT_SKIN = 'default'
+
+DISABLED_MODULES = ['books', 'recaptcha', 'project_badges']
diff --git a/forum/modules/template_loader.py/tmp/README b/forum/modules/template_loader.py/tmp/README
new file mode 100644 (file)
index 0000000..708174a
--- /dev/null
@@ -0,0 +1 @@
+Just an empty placeholder.
\ No newline at end of file
diff --git a/forum/modules/template_loader.py/urls.py b/forum/modules/template_loader.py/urls.py
new file mode 100644 (file)
index 0000000..0355657
--- /dev/null
@@ -0,0 +1,13 @@
+from django.conf.urls.defaults import *
+from django.utils.translation import ugettext as _
+from django.conf import settings
+
+urlpatterns = patterns('',
+    (r'', include('forum.urls')),
+)
+
+if 'rosetta' in settings.INSTALLED_APPS:
+    urlpatterns += patterns('',
+        url(r'^rosetta/', include('rosetta.urls')),
+    )
+