Merge branch 'master' of github.com:plone/plone.app.discussion

Conflicts:
	plone/app/discussion/locales/ja/LC_MESSAGES/plone.app.discussion.po
This commit is contained in:
Manabu TERADA 2015-04-29 17:39:14 +09:00
commit b235f74f46
127 changed files with 8369 additions and 5256 deletions

3
.gitignore vendored
View File

@ -8,12 +8,15 @@
/build
/dist
/local.cfg
.coverage
/*.egg-info
/*.egg
/.installed.cfg
*.pyc
/.Python
/include
/lib
/local
/.project
/.pydevproject
/.mr.developer.cfg

19
.travis.yml Normal file
View File

@ -0,0 +1,19 @@
language: python
python: "2.7"
sudo: false
cache:
directories:
- eggs
before_install:
- pip install http://effbot.org/downloads/Imaging-1.1.7.tar.gz
install:
- mkdir -p buildout-cache/eggs
- mkdir -p buildout-cache/downloads
- python bootstrap-buildout.py --setuptools-version=8.3 -c travis.cfg
- bin/buildout -N -t 3 -c travis.cfg
script:
- bin/code-analysis
# - bin/test-coverage
#after_success:
# - pip install -q coveralls
# - coveralls

View File

@ -1,9 +1,275 @@
Changelog
=========
2.2.1 (unreleased)
2.4.2 (unreleased)
------------------
- Nothing changed yet.
2.4.1 (2015-03-26)
------------------
- i18n for ICaptcha interface.
[davidjb]
2.4.0 (2015-03-12)
------------------
- use requirejs if available
[vangheem]
- Rename @@discussion-settings to @@discussion-controlpanel
[maartenkling]
- Add permission to allow comment authors to delete their own comments if
there are no replies yet.
[gaudenz]
- Updated portuguese pt-br translation.
[jtmolon]
- Read mail settings from new (Plone 5) registry.
[timo]
- Remove @property from Conversation.total_comments as @property and
Acquisition don't play well together.
[gforcada]
2.3.3 (2014-10-23)
------------------
- Don't execute createReplyForm js if there is no in_reply_to button.
[vincentfretin]
- Register events as Content Rules Event Types if plone.contentrules is present
[avoinea]
- Trigger custom events on comment add/remove/reply
[avoinea]
- Replace $.live with $.on for jQuery >= 1.9 compatibility. This works on
jQuery >= 1.7 (Plone 4.3 onwards).
[gaudenz]
- Update Traditional Chinese translations.
[marr]
- Make comments editable.
[pjstevns, gyst]
- Provide 'Delete comments' permission to handle comments deletion
[cekk]
- Fixed Italian translations [cekk]
2.3.2 (2014-04-05)
------------------
- bugfix: according to IDiscussionSettings.anonymous_email_enabled (cite):
"If selected, anonymous user will have to give their email." - But field
was not required. Now it is.
[jensens]
- bugfix: anonymous email field was never saved.
[jensens]
- updated german translations: added some missing msgstr.
[jensens]
- added i18ndude and a script ``update_translations`` to buildout in order
to make translation updates simpler.
[jensens]
- Fix reindexObject for content_object in moderation views.
Now reindex only "total_comments" index and not all the indexes
[cekk]
- Fix comments Title if utf-8 characters in author_name
[huub_bouma]
- use member.getId as author_username, so membrane users having different id
then username still have there picture shown and author path is correct.
[maartenkling]
2.3.1 (2014-02-22)
------------------
- 2.3.0 was a brown bag release.
[timo]
2.3.0 (2014-02-22)
------------------
- Remove DL's from portal message in templates.
https://github.com/plone/Products.CMFPlone/issues/153
[khink]
- Execute the proper workflow change when using the moderation buttons instead
of hardcoding the workflow action to always publish
[omiron]
- Corrections and additions to the Danish translation
[aputtu]
2.2.12 (2014-01-13)
-------------------
- Show author email to Moderator when it is available in anonymous comment.
[gotcha, smoussiaux]
- Put defaultUser.png instead of old defaultUser.gif
[bsuttor]
- Remove bbb directory. bbb was never really implemented.
[timo]
- Replace deprecated test assert statements.
[timo]
- Remove portal_discussion tool.
[timo]
- Refactor tests to use the PLONE_APP_CONTENTTYPES_FIXTURE instead of
PLONE_FIXTURE.
[timo]
- Fix ownership of comments.
[toutpt]
2.2.10 (2013-09-24)
-------------------
- Revert "Refactor tests to use the PLONE_APP_CONTENTTYPES_FIXTURE instead of
the PLONE_FIXTURE." that has been accidentially introduced into the 2.2.9
release.
[timo]
2.2.9 (2013-09-24)
------------------
- Portuguese translation added.
[Rui Silva]
- Rename CHANGES.txt to CHANGES.rst.
[timo]
- Fix ajax form submit for delete comment action: add 'data' to the request.
[toutpt]
2.2.8 (2013-08-20)
------------------
- Re-release 2.2.7 with .mo files. Seems like 2.2.7 has been released twice on
two different dates. The first release seems to be made without a github
push.
[timo]
- Fix comments viewlet's get_replies for non-annotatable objects.
[witsch]
2.2.7 (2013-07-04)
------------------
- making sure .mo files are present at release
[garbas]
- Revert change that silently added mime_type attribute values
to old discussion items that had none.
[pjstevns]
2.2.6 (2013-05-23)
------------------
- Fix migration to not fail when member has been deleted.
[datakurre]
2.2.5 (2013-04-06)
------------------
- Update pt_BR translation [ericof]
- Do not raise an error when no workflow is assigned to the comment type.
[timo]
- Add a conversation property public_commentators that only lists
commentators of comments that are public.
The commentators indexer indexes this field now.
The behavior of the conversation property commentators is
unchanged.
[do3cc]
- The last comment date now only returns the date of the newest
published comment.
[do3cc]
2.2.4 (2013-03-05)
------------------
- Check for 'checked' attribute in a way that work also for jQuery 1.7
[ichimdav]
- Better fix for #13037 by removing submit event trigger altogether
[ichimdav]
- Added Romanian translation
[ichimdav]
- Updated Ukrainian translation
[kroman0]
2.2.3 (2013-01-13)
------------------
- add anonymous_email_enabled settings to really let integrator activate
the email field on comment add form when anonymous.
[toutpt]
2.2.2 (2012-11-16)
------------------
- first check if captcha is installed before we open browsers zcml
files that depend on these packages, fixes #12118 and #12774
[maartenkling]
2.2.1 (2012-11-16)
------------------
- Make conversation view not break when comment-id cannot be converted to
long. This fixes #13327
[khink]
- fix insufficient privileges when trying to view
the RSS feed of a comment collection
[maartenkling]
- removed inline border=0 and move it to css
[maartenkling]
- For migrations of comments without a valid old_status, apply the 'published'
state.
[thet]
- Re-apply eleddy's "Revert modification date since this is fixed in
p.a.caching now." as her commit was lost later on due to some git magic.
[thet]
- Remove submitting the controlpanel form again after removing disabled tags
fixes #13037 and #12357
[maartenkling]

View File

@ -1,4 +1,5 @@
include *.txt
include *.rst
recursive-include docs *
recursive-include plone *

View File

@ -1,6 +1,7 @@
Introduction
============
plone.app.discussion replaces the old commenting system in Plone 4.1 and is also
available as an add-on product for Plone 3 and 4. It was initially developed as
part of the Google Summer of Code 2009 by Timo Stollenwerk (student) and Martin
@ -28,8 +29,8 @@ Requirements
Plone 3.3 or later.
Plone 3.x Buildout Installation
===============================
Plone 3.3.x Buildout Installation
=================================
To install plone.app.discussion, add the following code to your buildout.cfg::
@ -55,7 +56,7 @@ To install plone.app.discussion, add the following code to your buildout.cfg::
...
Plone 4.x Buildout Installation
Plone 4.0 Buildout Installation
===============================
To install plone.app.discussion, add the following code to your buildout.cfg::
@ -144,3 +145,4 @@ Many thanks to:
- Hanno Schlichting (for making p.a.d work with Zope 2.12)
- Alan Hoey (for providing fixes)
- Maik Roeder (for providing and setting up a buildbot)

189
bootstrap-buildout.py Normal file
View File

@ -0,0 +1,189 @@
##############################################################################
#
# Copyright (c) 2006 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Bootstrap a buildout-based project
Simply run this script in a directory containing a buildout.cfg.
The script accepts buildout command-line options, so you can
use the -c option to specify an alternate configuration file.
"""
import os
import shutil
import sys
import tempfile
from optparse import OptionParser
tmpeggs = tempfile.mkdtemp()
usage = '''\
[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
Bootstraps a buildout-based project.
Simply run this script in a directory containing a buildout.cfg, using the
Python that you want bin/buildout to use.
Note that by using --find-links to point to local resources, you can keep
this script from going over the network.
'''
parser = OptionParser(usage=usage)
parser.add_option("-v", "--version", help="use a specific zc.buildout version")
parser.add_option("-t", "--accept-buildout-test-releases",
dest='accept_buildout_test_releases',
action="store_true", default=False,
help=("Normally, if you do not specify a --version, the "
"bootstrap script and buildout gets the newest "
"*final* versions of zc.buildout and its recipes and "
"extensions for you. If you use this flag, "
"bootstrap and buildout will get the newest releases "
"even if they are alphas or betas."))
parser.add_option("-c", "--config-file",
help=("Specify the path to the buildout configuration "
"file to be used."))
parser.add_option("-f", "--find-links",
help=("Specify a URL to search for buildout releases"))
parser.add_option("--allow-site-packages",
action="store_true", default=False,
help=("Let bootstrap.py use existing site packages"))
parser.add_option("--setuptools-version",
help="use a specific setuptools version")
options, args = parser.parse_args()
######################################################################
# load/install setuptools
try:
if options.allow_site_packages:
import setuptools
import pkg_resources
from urllib.request import urlopen
except ImportError:
from urllib2 import urlopen
ez = {}
exec(urlopen('https://bootstrap.pypa.io/ez_setup.py').read(), ez)
if not options.allow_site_packages:
# ez_setup imports site, which adds site packages
# this will remove them from the path to ensure that incompatible versions
# of setuptools are not in the path
import site
# inside a virtualenv, there is no 'getsitepackages'.
# We can't remove these reliably
if hasattr(site, 'getsitepackages'):
for sitepackage_path in site.getsitepackages():
sys.path[:] = [x for x in sys.path if sitepackage_path not in x]
setup_args = dict(to_dir=tmpeggs, download_delay=0)
if options.setuptools_version is not None:
setup_args['version'] = options.setuptools_version
ez['use_setuptools'](**setup_args)
import setuptools
import pkg_resources
# This does not (always?) update the default working set. We will
# do it.
for path in sys.path:
if path not in pkg_resources.working_set.entries:
pkg_resources.working_set.add_entry(path)
######################################################################
# Install buildout
ws = pkg_resources.working_set
cmd = [sys.executable, '-c',
'from setuptools.command.easy_install import main; main()',
'-mZqNxd', tmpeggs]
find_links = os.environ.get(
'bootstrap-testing-find-links',
options.find_links or
('http://downloads.buildout.org/'
if options.accept_buildout_test_releases else None)
)
if find_links:
cmd.extend(['-f', find_links])
setuptools_path = ws.find(
pkg_resources.Requirement.parse('setuptools')).location
requirement = 'zc.buildout'
version = options.version
if version is None and not options.accept_buildout_test_releases:
# Figure out the most recent final version of zc.buildout.
import setuptools.package_index
_final_parts = '*final-', '*final'
def _final_version(parsed_version):
try:
return not parsed_version.is_prerelease
except AttributeError:
# Older setuptools
for part in parsed_version:
if (part[:1] == '*') and (part not in _final_parts):
return False
return True
index = setuptools.package_index.PackageIndex(
search_path=[setuptools_path])
if find_links:
index.add_find_links((find_links,))
req = pkg_resources.Requirement.parse(requirement)
if index.obtain(req) is not None:
best = []
bestv = None
for dist in index[req.project_name]:
distv = dist.parsed_version
if _final_version(distv):
if bestv is None or distv > bestv:
best = [dist]
bestv = distv
elif distv == bestv:
best.append(dist)
if best:
best.sort()
version = best[-1].version
if version:
requirement = '=='.join((requirement, version))
cmd.append(requirement)
import subprocess
if subprocess.call(cmd, env=dict(os.environ, PYTHONPATH=setuptools_path)) != 0:
raise Exception(
"Failed to execute command:\n%s" % repr(cmd)[1:-1])
######################################################################
# Import and run buildout
ws.add_entry(tmpeggs)
ws.require(requirement)
import zc.buildout.buildout
if not [a for a in args if '=' not in a]:
args.append('bootstrap')
# if -c was provided, we push it back into args for buildout' main function
if options.config_file is not None:
args[0:0] = ['-c', options.config_file]
zc.buildout.buildout.main(args)
shutil.rmtree(tmpeggs)

88
buildout.cfg Normal file
View File

@ -0,0 +1,88 @@
[buildout]
extends = http://dist.plone.org/release/4.3.4/versions.cfg
parts =
instance
test
coverage
test-coverage
mkrelease
pocompile
code-analysis
i18ndude
update_translations
develop = .
[instance]
recipe = plone.recipe.zope2instance
http-address = 8080
user = admin:admin
eggs = Plone
[test]
recipe = zc.recipe.testrunner
eggs = plone.app.discussion [test]
defaults = ['-s', 'plone.app.discussion', '--auto-color', '--auto-progress']
[coverage]
recipe = zc.recipe.egg
eggs = coverage
[test-coverage]
recipe = collective.recipe.template
input = inline:
#!/bin/bash
${buildout:directory}/bin/coverage run --source=${buildout:directory}/src/plone/app/discussion bin/test
${buildout:directory}/bin/coverage html
${buildout:directory}/bin/coverage report -m --fail-under=100
# Fail (exit status 1) if coverage returns exit status 2 (this happens
# when test coverage is below 100%.
output = ${buildout:directory}/bin/test-coverage
mode = 755
[mkrelease]
recipe = zc.recipe.egg
eggs = jarn.mkrelease
[pocompile]
recipe = zc.recipe.egg
eggs = zest.pocompile
[code-analysis]
recipe = plone.recipe.codeanalysis
directory = ${buildout:directory}/plone/app/discussion
flake8-max-complexity = 50
[i18ndude]
recipe = zc.recipe.egg
eggs =
i18ndude
[update_translations]
recipe = collective.recipe.template
output = ${buildout:bin-directory}/update_translations
input = inline:
#!/usr/bin/env bash
DOMAIN="plone.app.discussion"
BASE_PATH=${buildout:directory}/plone/app/discussion
I18NDUDE=${buildout:bin-directory}/i18ndude
$I18NDUDE rebuild-pot --pot $BASE_PATH/locales/$DOMAIN.pot --create "$DOMAIN" $BASE_PATH*
$I18NDUDE rebuild-pot --pot $BASE_PATH/i18n/plone.pot --create "plone" $BASE_PATH/profiles/
for LANG in `find $BASE_PATH/locales -maxdepth 1 -mindepth 1 -type d \
| sed -e "s/.*locales\/\(.*\)$/\1/"`; do
$I18NDUDE sync --pot $BASE_PATH/locales/$DOMAIN.pot $BASE_PATH/locales/de/LC_MESSAGES/$DOMAIN.po
msgfmt --no-hash -o $BASE_PATH/locales/$LANG/LC_MESSAGES/$DOMAIN.mo $BASE_PATH/locales/$LANG/LC_MESSAGES/$DOMAIN.po
$I18NDUDE sync --pot $BASE_PATH/i18n/plone.pot $BASE_PATH/i18n/plone-$LANG.po
msgfmt --no-hash -o $BASE_PATH/i18n/plone-$LANG.mo $BASE_PATH/i18n/plone-$LANG.po
done
mode = 755
[versions]
plone.app.discussion =
zope.interface = 4.0.5
zc.buildout = 2.3.1
setuptools = 8.0.4

View File

@ -1 +0,0 @@
.. include:: ../../CHANGES.txt

View File

@ -21,7 +21,6 @@ Contents:
email-notification.txt
api/index.txt
howtos/index.txt
changes.txt

View File

@ -1,8 +1,16 @@
from Acquisition import aq_inner, aq_parent
from AccessControl import getSecurityManager
from zope.component import getMultiAdapter
from Products.statusmessages.interfaces import IStatusMessage
from Products.Five.browser import BrowserView
from Products.CMFCore.utils import getToolByName
from plone.app.discussion import PloneAppDiscussionMessageFactory as _
from comments import CommentForm
from z3c.form import button
from plone.z3cform.layout import wrap_form
class View(BrowserView):
"""Comment View.
@ -37,3 +45,64 @@ class View(BrowserView):
url = "%s/view" % url
self.request.response.redirect('%s#%s' % (url, context.id))
class EditCommentForm(CommentForm):
"""Form to edit an existing comment."""
ignoreContext = True
id = "edit-comment-form"
label = _(u'edit_comment_form_title', default=u'Edit comment')
def updateWidgets(self):
super(EditCommentForm, self).updateWidgets()
self.widgets['text'].value = self.context.text
# We have to rename the id, otherwise TinyMCE can't initialize
# because there are two textareas with the same id.
self.widgets['text'].id = 'overlay-comment-text'
def _redirect(self, target=''):
if not target:
portal_state = getMultiAdapter((self.context, self.request),
name=u'plone_portal_state')
target = portal_state.portal_url()
self.request.response.redirect(target)
@button.buttonAndHandler(_(u"edit_comment_form_button",
default=u"Edit comment"), name='comment')
def handleComment(self, action):
# Validate form
data, errors = self.extractData()
if errors:
return
# Check permissions
can_edit = getSecurityManager().checkPermission(
'Edit comments',
self.context)
mtool = getToolByName(self.context, 'portal_membership')
if mtool.isAnonymousUser() or not can_edit:
return
# Update text
self.context.text = data['text']
# Redirect to comment
IStatusMessage(self.request).add(_(u'comment_edit_notification',
default="Comment was edited"),
type='info')
return self._redirect(
target=self.action.replace("@@edit-comment", "@@view"))
@button.buttonAndHandler(_(u'cancel_form_button',
default=u'Cancel'), name='cancel')
def handle_cancel(self, action):
IStatusMessage(self.request).add(
_(u'comment_edit_cancel_notification',
default=u'Edit comment cancelled'),
type='info')
return self._redirect(target=self.context.absolute_url())
EditComment = wrap_form(EditCommentForm)
#EOF

View File

@ -1,6 +1,8 @@
<tal:block tal:define="userHasReplyPermission view/can_reply;
isDiscussionAllowed view/is_discussion_allowed;
isAnonymousDiscussionAllowed view/anonymous_discussion_allowed;
isEditCommentAllowed view/edit_comment_allowed;
isDeleteOwnCommentAllowed view/delete_own_comment_allowed;
isAnon view/is_anonymous;
canReview view/can_review;
replies python:view.get_replies(canReview);
@ -34,7 +36,9 @@
author_home_url python:view.get_commenter_home_url(username=reply.author_username);
has_author_link python:author_home_url and not isAnon;
portrait_url python:view.get_commenter_portrait(reply.author_username);
review_state python:wtool.getInfoFor(reply, 'review_state', 'none');"
review_state python:wtool.getInfoFor(reply, 'review_state', 'none');
canEdit python:view.can_edit(reply);
canDelete python:view.can_delete(reply)"
tal:attributes="class python:'comment replyTreeLevel'+str(depth)+' state-'+str(review_state);
id string:${reply/getId}"
tal:condition="python:canReview or review_state == 'published'">
@ -42,16 +46,16 @@
<div class="commentImage" tal:condition="showCommenterImage">
<a href="" tal:condition="has_author_link"
tal:attributes="href author_home_url">
<img src="defaultUser.gif"
<img src="defaultUser.png"
alt=""
border="0"
class="defaultuserimg"
height="32"
tal:attributes="src portrait_url;
alt reply/author_name" />
</a>
<img src="defaultUser.gif"
<img src="defaultUser.png"
alt=""
border="0"
class="defaultuserimg"
height="32"
tal:condition="not: has_author_link"
tal:attributes="src portrait_url;
@ -87,7 +91,21 @@
action=""
method="post"
class="commentactionsform"
tal:condition="canReview"
tal:condition="python:not canDelete and isDeleteOwnCommentAllowed and view.could_delete_own(reply)"
tal:attributes="action string:${reply/absolute_url}/@@delete-own-comment;
style python:view.can_delete_own(reply) and 'display: inline' or 'display: none'">
<input name="form.button.DeleteComment"
class="destructive"
type="submit"
value="Delete"
i18n:attributes="value label_delete;"
/>
</form>
<form name="delete"
action=""
method="post"
class="commentactionsform"
tal:condition="python:canDelete"
tal:attributes="action string:${reply/absolute_url}/@@moderate-delete-comment">
<input name="form.button.DeleteComment"
class="destructive"
@ -97,6 +115,21 @@
/>
</form>
<form name="edit"
action=""
method="get"
class="commentactionsform"
tal:condition="python:isEditCommentAllowed and canEdit"
tal:attributes="action string:${reply/absolute_url}/@@edit-comment">
<input name="form.button.EditComment"
class="context"
type="submit"
value="Edit"
i18n:attributes="value label_edit;"
/>
</form>
<!-- Workflow actions (e.g. 'publish') -->
<form name=""
action=""

View File

@ -46,19 +46,19 @@ from plone.z3cform.interfaces import IWrappedForm
COMMENT_DESCRIPTION_PLAIN_TEXT = _(
u"comment_description_plain_text",
default=u"You can add a comment by filling out the form below. " +
"Plain text formatting.")
u"Plain text formatting.")
COMMENT_DESCRIPTION_MARKDOWN = _(
u"comment_description_markdown",
default=u"You can add a comment by filling out the form below. " +
"Plain text formatting. You can use the Markdown syntax for " +
"links and images.")
u"Plain text formatting. You can use the Markdown syntax for " +
u"links and images.")
COMMENT_DESCRIPTION_INTELLIGENT_TEXT = _(
u"comment_description_intelligent_text",
default=u"You can add a comment by filling out the form below. " +
"Plain text formatting. Web and email addresses are " +
"transformed into clickable links.")
u"Plain text formatting. Web and email addresses are " +
u"transformed into clickable links.")
COMMENT_DESCRIPTION_MODERATION_ENABLED = _(
u"comment_description_moderation_enabled",
@ -101,26 +101,32 @@ class CommentForm(extensible.ExtensibleForm, form.Form):
# Anonymous / Logged-in
mtool = getToolByName(self.context, 'portal_membership')
if not mtool.isAnonymousUser():
self.widgets['author_name'].mode = interfaces.HIDDEN_MODE
self.widgets['author_email'].mode = interfaces.HIDDEN_MODE
# Todo: Since we are not using the author_email field in the
# current state, we hide it by default. But we keep the field for
# integrators or later use.
self.widgets['author_email'].mode = interfaces.HIDDEN_MODE
anon = mtool.isAnonymousUser()
registry = queryUtility(IRegistry)
settings = registry.forInterface(IDiscussionSettings, check=False)
if anon:
if settings.anonymous_email_enabled:
# according to IDiscussionSettings.anonymous_email_enabled:
# "If selected, anonymous user will have to give their email."
self.widgets['author_email'].field.required = True
self.widgets['author_email'].required = True
else:
self.widgets['author_email'].mode = interfaces.HIDDEN_MODE
else:
self.widgets['author_name'].mode = interfaces.HIDDEN_MODE
self.widgets['author_email'].mode = interfaces.HIDDEN_MODE
member = mtool.getAuthenticatedMember()
member_email = member.getProperty('email')
# Hide the user_notification checkbox if user notification is disabled
# or the user is not logged in. Also check if the user has a valid
# email address
if member_email == '' or \
not settings.user_notification_enabled or \
mtool.isAnonymousUser():
member_email_is_empty = member_email == ''
user_notification_disabled = not settings.user_notification_enabled
if member_email_is_empty or user_notification_disabled or anon:
self.widgets['user_notification'].mode = interfaces.HIDDEN_MODE
def updateActions(self):
@ -136,7 +142,8 @@ class CommentForm(extensible.ExtensibleForm, form.Form):
# Check if conversation is enabled on this content object
if not self.__parent__.restrictedTraverse(
'@@conversation_view').enabled():
'@@conversation_view'
).enabled():
raise Unauthorized("Discussion is not enabled for this content "
"object.")
@ -149,9 +156,10 @@ class CommentForm(extensible.ExtensibleForm, form.Form):
registry = queryUtility(IRegistry)
settings = registry.forInterface(IDiscussionSettings, check=False)
portal_membership = getToolByName(self.context, 'portal_membership')
if settings.captcha != 'disabled' and \
settings.anonymous_comments and \
portal_membership.isAnonymousUser():
captcha_enabled = settings.captcha != 'disabled'
anonymous_comments = settings.anonymous_comments
anon = portal_membership.isAnonymousUser()
if captcha_enabled and anonymous_comments and anon:
if not 'captcha' in data:
data['captcha'] = u""
captcha = CaptchaValidator(self.context,
@ -173,28 +181,32 @@ class CommentForm(extensible.ExtensibleForm, form.Form):
# Set comment attributes (including extended comment form attributes)
for attribute in self.fields.keys():
setattr(comment, attribute, data[attribute])
# Make sure author_name is properly encoded
# Make sure author_name/ author_email is properly encoded
if 'author_name' in data:
author_name = data['author_name']
if isinstance(author_name, str):
author_name = unicode(author_name, 'utf-8')
if 'author_email' in data:
author_email = data['author_email']
if isinstance(author_email, str):
author_email = unicode(author_email, 'utf-8')
# Set comment author properties for anonymous users or members
can_reply = getSecurityManager().checkPermission('Reply to item',
context)
portal_membership = getToolByName(self.context, 'portal_membership')
if portal_membership.isAnonymousUser() and \
settings.anonymous_comments:
if anon and anonymous_comments:
# Anonymous Users
comment.author_name = author_name
comment.author_email = u""
comment.author_email = author_email
comment.user_notification = None
comment.creation_date = datetime.utcnow()
comment.modification_date = datetime.utcnow()
elif not portal_membership.isAnonymousUser() and can_reply:
# Member
member = portal_membership.getAuthenticatedMember()
username = member.getUserName()
memberid = member.getId()
user = member.getUser()
email = member.getProperty('email')
fullname = member.getProperty('fullname')
if not fullname or fullname == '':
@ -204,16 +216,27 @@ class CommentForm(extensible.ExtensibleForm, form.Form):
fullname = unicode(fullname, 'utf-8')
if email and isinstance(email, str):
email = unicode(email, 'utf-8')
comment.creator = username
comment.author_username = username
comment.changeOwnership(user, recursive=False)
comment.manage_setLocalRoles(memberid, ["Owner"])
comment.creator = memberid
comment.author_username = memberid
comment.author_name = fullname
# XXX: according to IComment interface author_email must not be
# set for logged in users, cite:
# "for anonymous comments only, set to None for logged in comments"
comment.author_email = email
# /XXX
comment.creation_date = datetime.utcnow()
comment.modification_date = datetime.utcnow()
else: # pragma: no cover
raise Unauthorized("Anonymous user tries to post a comment, but "
"anonymous commenting is disabled. Or user does not have the "
"'reply to item' permission.")
raise Unauthorized(
u"Anonymous user tries to post a comment, but anonymous "
u"commenting is disabled. Or user does not have the "
u"'reply to item' permission."
)
# Add comment to conversation
conversation = IConversation(self.__parent__)
@ -234,7 +257,11 @@ class CommentForm(extensible.ExtensibleForm, form.Form):
can_review = getSecurityManager().checkPermission('Review comments',
context)
workflowTool = getToolByName(context, 'portal_workflow')
comment_review_state = workflowTool.getInfoFor(comment, 'review_state')
comment_review_state = workflowTool.getInfoFor(
comment,
'review_state',
None
)
if comment_review_state == 'pending' and not can_review:
# Show info message when comment moderation is enabled
IStatusMessage(self.context.REQUEST).addStatusMessage(
@ -259,9 +286,13 @@ class CommentsViewlet(ViewletBase):
def update(self):
super(CommentsViewlet, self).update()
if self.is_discussion_allowed() and \
(self.is_anonymous() and self.anonymous_discussion_allowed() \
or self.can_reply()):
discussion_allowed = self.is_discussion_allowed()
anonymous_allowed_or_can_reply = (
self.is_anonymous()
and self.anonymous_discussion_allowed()
or self.can_reply()
)
if discussion_allowed and anonymous_allowed_or_can_reply:
z2.switch_on(self, request_layer=IFormLayer)
self.form = self.form(aq_inner(self.context), self.request)
alsoProvides(self.form, IWrappedForm)
@ -287,6 +318,40 @@ class CommentsViewlet(ViewletBase):
return getSecurityManager().checkPermission('Review comments',
aq_inner(self.context))
def can_delete_own(self, comment):
"""Returns true if the current user can delete the comment. Only
comments without replies can be deleted.
"""
try:
return comment.restrictedTraverse(
'@@delete-own-comment').can_delete()
except Unauthorized:
return False
def could_delete_own(self, comment):
"""Returns true if the current user could delete the comment if it had
no replies. This is used to prepare hidden form buttons for JS.
"""
try:
return comment.restrictedTraverse(
'@@delete-own-comment').could_delete()
except Unauthorized:
return False
def can_edit(self, reply):
"""Returns true if current user has the 'Edit comments'
permission.
"""
return getSecurityManager().checkPermission('Edit comments',
aq_inner(reply))
def can_delete(self, reply):
"""Returns true if current user has the 'Delete comments'
permission.
"""
return getSecurityManager().checkPermission('Delete comments',
aq_inner(reply))
def is_discussion_allowed(self):
context = aq_inner(self.context)
return context.restrictedTraverse('@@conversation_view').enabled()
@ -347,10 +412,12 @@ class CommentsViewlet(ViewletBase):
returned with workflow actions.
"""
context = aq_inner(self.context)
conversation = IConversation(context)
conversation = IConversation(context, None)
if conversation is None:
return iter([])
wf = getToolByName(context, 'portal_workflow')
# workflow_actions is only true when user
# has 'Manage portal' permission
@ -359,8 +426,10 @@ class CommentsViewlet(ViewletBase):
for r in conversation.getThreads():
comment_obj = r['comment']
# list all possible workflow actions
actions = [a for a in wf.listActionInfos(object=comment_obj)
if a['category'] == 'workflow' and a['allowed']]
actions = [
a for a in wf.listActionInfos(object=comment_obj)
if a['category'] == 'workflow' and a['allowed']
]
r = r.copy()
r['actions'] = actions
yield r
@ -392,12 +461,13 @@ class CommentsViewlet(ViewletBase):
if username is None:
# return the default user image if no username is given
return 'defaultUser.gif'
return 'defaultUser.png'
else:
portal_membership = getToolByName(self.context,
'portal_membership',
None)
return portal_membership.getPersonalPortrait(username)\
return portal_membership\
.getPersonalPortrait(username)\
.absolute_url()
def anonymous_discussion_allowed(self):
@ -406,6 +476,18 @@ class CommentsViewlet(ViewletBase):
settings = registry.forInterface(IDiscussionSettings, check=False)
return settings.anonymous_comments
def edit_comment_allowed(self):
# Check if editing comments is allowed in the registry
registry = queryUtility(IRegistry)
settings = registry.forInterface(IDiscussionSettings, check=False)
return settings.edit_comment_enabled
def delete_own_comment_allowed(self):
# Check if delete own comments is allowed in the registry
registry = queryUtility(IRegistry)
settings = registry.forInterface(IDiscussionSettings, check=False)
return settings.delete_own_comment_enabled
def show_commenter_image(self):
# Check if showing commenter image is enabled in the registry
registry = queryUtility(IRegistry)

View File

@ -71,13 +71,32 @@
permission="zope2.View"
/>
<!-- Delete comment view -->
<!-- Edit comment view -->
<browser:page
for="plone.app.discussion.interfaces.IComment"
name="edit-comment"
layer="..interfaces.IDiscussionLayer"
class=".comment.EditComment"
permission="plone.app.discussion.EditComments"
/>
<!-- Delete comment views
has conditional security dependent on controlpanel settings.
-->
<browser:page
for="plone.app.discussion.interfaces.IComment"
name="moderate-delete-comment"
layer="..interfaces.IDiscussionLayer"
class=".moderation.DeleteComment"
permission="plone.app.discussion.ReviewComments"
permission="plone.app.discussion.DeleteComments"
/>
<browser:page
for="plone.app.discussion.interfaces.IComment"
name="delete-own-comment"
layer="..interfaces.IDiscussionLayer"
class=".moderation.DeleteOwnComment"
permission="plone.app.discussion.DeleteOwnComments"
/>
<!-- Publish comment view -->
@ -133,6 +152,13 @@
/>
<!-- Control panel -->
<browser:page
name="discussion-controlpanel"
for="Products.CMFPlone.interfaces.IPloneSiteRoot"
class=".controlpanel.DiscussionSettingsControlPanel"
permission="cmf.ManagePortal"
/>
<!-- Deprecated controlpanel url -->
<browser:page
name="discussion-settings"
for="Products.CMFPlone.interfaces.IPloneSiteRoot"

View File

@ -6,28 +6,18 @@
metal:use-macro="here/prefs_main_template/macros/master"
i18n:domain="plone">
<metal:javascript_head_slot fill-slot="javascript_head_slot">
<script type="text/javascript"
tal:attributes="src string:${context/portal_url}/++resource++plone.app.discussion.javascripts/controlpanel.js">
</script>
</metal:javascript_head_slot>
<body>
<div id="content"
<article id="content"
tal:attributes="class view/settings"
metal:fill-slot="prefs_configlet_content">
<script type="text/javascript"
tal:attributes="src string:${context/portal_url}/++resource++plone.app.discussion.javascripts/controlpanel.js">
</script>
<dl class="portalMessage warning"
<div class="portalMessage warning"
tal:condition="view/mailhost_warning">
<dt i18n:translate="">
<strong i18n:translate="">
Warning
</dt>
<dd i18n:translate="text_no_mailhost_configured">
</strong>
<span tal:omit-tag="" i18n:translate="text_no_mailhost_configured">
You have not configured a mail host or a site 'From'
address, various features including contact forms, email
notification and password reset will not work. Go to the
@ -38,15 +28,15 @@
>Mail control panel</a>
</tal:link>
to fix this.
</dd>
</dl>
</span>
</div>
<dl class="portalMessage warning"
<div class="portalMessage warning"
tal:condition="view/custom_comment_workflow_warning">
<dt i18n:translate="">
<strong i18n:translate="">
Warning
</dt>
<dd i18n:translate="text_custom_comment_workflow">
</strong>
<span tal:omit-tag="" i18n:translate="text_custom_comment_workflow">
You have configured a custom workflow for the 'Discussion Item'
content type. You can enable/disable the comment moderation
in this control panel only if you use one of the default
@ -58,15 +48,15 @@
>Types control panel</a>
</tal:link>
to choose a workflow for the 'Discussion Item' type.
</dd>
</dl>
</span>
</div>
<dl class="portalMessage warning"
<div class="portalMessage warning"
tal:condition="view/unmigrated_comments_warning">
<dt i18n:translate="">
<strong i18n:translate="">
Warning
</dt>
<dd i18n:translate="text_unmigrated_comments">
</strong>
<span tal:omit-tag="" i18n:translate="text_unmigrated_comments">
You have comments that have not been migrated to the new
commenting system that has been introduced in Plone 4.1.
Please
@ -77,8 +67,8 @@
>migrate your comments</a>
</tal:link>
to fix this.
</dd>
</dl>
</span>
</div>
<div metal:use-macro="context/global_statusmessage/macros/portal_message">
Portal status message
@ -99,6 +89,9 @@
</div>
</div>
</div>
<script type="text/javascript"
tal:attributes="src string:${context/portal_url}/++resource++plone.app.discussion.javascripts/controlpanel.js">
</script>
</article>
</body>
</html>

View File

@ -1,10 +1,8 @@
# -*- coding: utf-8 -*-
from Acquisition import aq_base, aq_inner
from zope.component import getUtility
from Products.CMFCore.utils import getToolByName
from Products.CMFCore.interfaces._content import IDiscussionResponse
from Products.CMFPlone.interfaces.controlpanel import IMailSchema
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
@ -24,6 +22,7 @@ from z3c.form import button
from z3c.form.browser.checkbox import SingleCheckBoxFieldWidget
from plone.app.discussion.interfaces import IDiscussionSettings, _
from plone.app.discussion.upgrades import update_registry
class DiscussionSettingsEditForm(controlpanel.RegistryEditForm):
@ -32,16 +31,18 @@ class DiscussionSettingsEditForm(controlpanel.RegistryEditForm):
schema = IDiscussionSettings
id = "DiscussionSettingsEditForm"
label = _(u"Discussion settings")
description = _(u"help_discussion_settings_editform",
description = _(
u"help_discussion_settings_editform",
default=u"Some discussion related settings are not "
"located in the Discussion Control Panel.\n"
"To enable comments for a specific content type, "
"go to the Types Control Panel of this type and "
"choose \"Allow comments\".\n"
"To enable the moderation workflow for comments, "
"go to the Types Control Panel, choose "
"\"Comment\" and set workflow to "
"\"Comment Review Workflow\".")
u"located in the Discussion Control Panel.\n"
u"To enable comments for a specific content type, "
u"go to the Types Control Panel of this type and "
u"choose \"Allow comments\".\n"
u"To enable the moderation workflow for comments, "
u"go to the Types Control Panel, choose "
u"\"Comment\" and set workflow to "
u"\"Comment Review Workflow\"."
)
def updateFields(self):
super(DiscussionSettingsEditForm, self).updateFields()
@ -49,6 +50,10 @@ class DiscussionSettingsEditForm(controlpanel.RegistryEditForm):
SingleCheckBoxFieldWidget
self.fields['moderation_enabled'].widgetFactory = \
SingleCheckBoxFieldWidget
self.fields['edit_comment_enabled'].widgetFactory = \
SingleCheckBoxFieldWidget
self.fields['delete_own_comment_enabled'].widgetFactory = \
SingleCheckBoxFieldWidget
self.fields['anonymous_comments'].widgetFactory = \
SingleCheckBoxFieldWidget
self.fields['show_commenter_image'].widgetFactory = \
@ -59,6 +64,12 @@ class DiscussionSettingsEditForm(controlpanel.RegistryEditForm):
SingleCheckBoxFieldWidget
def updateWidgets(self):
try:
super(DiscussionSettingsEditForm, self).updateWidgets()
except KeyError:
# upgrade profile not visible in prefs_install_products_form
# provide auto-upgrade
update_registry(self.context)
super(DiscussionSettingsEditForm, self).updateWidgets()
self.widgets['globally_enabled'].label = _(u"Enable Comments")
self.widgets['anonymous_comments'].label = _(u"Anonymous Comments")
@ -77,7 +88,7 @@ class DiscussionSettingsEditForm(controlpanel.RegistryEditForm):
self.applyChanges(data)
IStatusMessage(self.request).addStatusMessage(_(u"Changes saved"),
"info")
self.context.REQUEST.RESPONSE.redirect("@@discussion-settings")
self.context.REQUEST.RESPONSE.redirect("@@discussion-controlpanel")
@button.buttonAndHandler(_('Cancel'), name='cancel')
def handleCancel(self, action):
@ -108,12 +119,20 @@ class DiscussionSettingsControlPanel(controlpanel.ControlPanelFormWrapper):
output.append("globally_enabled")
# Comment moderation
if 'one_state_workflow' not in workflow_chain and \
'comment_review_workflow' not in workflow_chain:
one_state_worklow_disabled = 'one_state_workflow' not in workflow_chain
comment_review_workflow_disabled = \
'comment_review_workflow' not in workflow_chain
if one_state_worklow_disabled and comment_review_workflow_disabled:
output.append("moderation_custom")
elif settings.moderation_enabled:
output.append("moderation_enabled")
if settings.edit_comment_enabled:
output.append("edit_comment_enabled")
if settings.delete_own_comment_enabled:
output.append("delte_own_comment_enabled")
# Anonymous comments
if settings.anonymous_comments:
output.append("anonymous_comments")
@ -136,12 +155,11 @@ class DiscussionSettingsControlPanel(controlpanel.ControlPanelFormWrapper):
def mailhost_warning(self):
"""Returns true if mailhost is not configured properly.
"""
# Copied from plone.app.controlpanel/plone/app/controlpanel/overview.py
mailhost = getToolByName(aq_inner(self.context), 'MailHost', None)
if mailhost is None:
return True
mailhost = getattr(aq_base(mailhost), 'smtp_host', None)
email = getattr(aq_inner(self.context), 'email_from_address', None)
# Copied from Products.CMFPlone/controlpanel/browser/overview.py
registry = getUtility(IRegistry)
mail_settings = registry.forInterface(IMailSchema, prefix='plone')
mailhost = mail_settings.smtp_host
email = mail_settings.email_from_address
if mailhost and email:
return False
return True
@ -151,15 +169,17 @@ class DiscussionSettingsControlPanel(controlpanel.ControlPanelFormWrapper):
"""
wftool = getToolByName(self.context, "portal_workflow", None)
workflow_chain = wftool.getChainForPortalType('Discussion Item')
if 'one_state_workflow' in workflow_chain \
or 'comment_review_workflow' in workflow_chain:
one_state_workflow_enabled = 'one_state_workflow' in workflow_chain
comment_review_workflow_enabled = \
'comment_review_workflow' in workflow_chain
if one_state_workflow_enabled or comment_review_workflow_enabled:
return
return True
def unmigrated_comments_warning(self):
"""Returns true if site contains unmigrated comments.
"""
catalog = getToolByName(aq_inner(self.context), 'portal_catalog', None)
catalog = getToolByName(self.context, 'portal_catalog', None)
count_comments_old = catalog.searchResults(
object_provides=IDiscussionResponse.__identifier__)
if count_comments_old:
@ -176,7 +196,7 @@ def notify_configuration_changed(event):
# Discussion control panel setting changed
if event.record.fieldName == 'moderation_enabled':
# Moderation enabled has changed
if event.record.value == True:
if event.record.value is True:
# Enable moderation workflow
wftool.setChainForPortalTypes(('Discussion Item',),
'comment_review_workflow')

View File

@ -64,8 +64,9 @@ class ConversationView(object):
return False
# Always return False if object is a folder
if (IFolderish.providedBy(context) and
not INonStructuralFolder.providedBy(context)):
context_is_folderish = IFolderish.providedBy(context)
context_is_structural = not INonStructuralFolder.providedBy(context)
if (context_is_folderish and context_is_structural):
return False
def traverse_parents(context):
@ -73,8 +74,9 @@ class ConversationView(object):
# enabled in a parent folder.
for obj in aq_chain(context):
if not IPloneSiteRoot.providedBy(obj):
if (IFolderish.providedBy(obj) and
not INonStructuralFolder.providedBy(obj)):
obj_is_folderish = IFolderish.providedBy(obj)
obj_is_stuctural = not INonStructuralFolder.providedBy(obj)
if (obj_is_folderish and obj_is_stuctural):
flag = getattr(obj, 'allow_discussion', None)
if flag is not None:
return flag

View File

@ -3,7 +3,20 @@
* jQuery functions for the plone.app.discussion comment viewlet and form.
*
******************************************************************************/
(function ($) {
/* global require */
if(require === undefined){
require = function(reqs, torun){ // jshint ignore:line
'use strict';
return torun(window.jQuery);
};
}
require([ // jshint ignore:line
'jquery'
], function ($) {
'use strict';
// This unnamed function allows us to use $ inside of a block of code
// without permanently overwriting $.
// http://docs.jquery.com/Using_jQuery_with_Other_Libraries
@ -14,58 +27,66 @@
**************************************************************************/
$.createReplyForm = function (comment_div) {
var comment_id = comment_div.attr("id");
var comment_id = comment_div.attr('id');
var reply_button = comment_div.find(".reply-to-comment-button");
var reply_button = comment_div.find('.reply-to-comment-button');
/* Clone the reply div at the end of the page template that contains
* the regular comment form.
*/
var reply_div = $("#commenting").clone(true);
var reply_div = $('#commenting').clone(true);
/* Remove the ReCaptcha JS code before appending the form. If not
* removed, this causes problems
*/
reply_div.find("#formfield-form-widgets-captcha")
.find("script")
reply_div.find('#formfield-form-widgets-captcha')
.find('script')
.remove();
/* Insert the cloned comment form right after the reply button of the
* current comment.
*/
reply_div.appendTo(comment_div).css("display", "none");
reply_div.appendTo(comment_div).css('display', 'none');
/* Remove id="reply" attribute, since we use it to uniquely
/* Remove id='commenting' attribute, since we use it to uniquely define
the main reply form. */
reply_div.removeAttr("id");
// Still belongs to class='reply'
reply_div.removeAttr('id');
/* Hide the reply button (only hide, because we may want to show it
* again if the user hits the cancel button).
*/
$(reply_button).css("display", "none");
$(reply_button).css('display', 'none');
/* Fetch the reply form inside the reply div */
var reply_form = reply_div.find("form");
var reply_form = reply_div.find('form');
/* Change the id of the textarea of the reply form
* To avoid conflict later between textareas with same id 'form-widgets-comment-text' while implementing a seperate instance of TinyMCE
* */
reply_form.find('#formfield-form-widgets-comment-text').attr('id', 'formfield-form-widgets-new-textarea'+comment_id );
reply_form.find('#form-widgets-comment-text').attr('id', 'form-widgets-new-textarea'+comment_id );
/* Populate the hidden 'in_reply_to' field with the correct comment
id */
reply_form.find("input[name='form.widgets.in_reply_to']")
reply_form.find('input[name="form.widgets.in_reply_to"]')
.val(comment_id);
/* Add a remove-reply-to-comment Javascript function to remove the
form */
var cancel_reply_button = reply_div.find(".cancelreplytocomment");
cancel_reply_button.attr("id", comment_id);
var cancel_reply_button = reply_div.find('.cancelreplytocomment');
cancel_reply_button.attr('id', comment_id);
/* Show the cancel buttons. */
reply_form.find("input[name='form.buttons.cancel']")
.css("display", "inline");
reply_form.find('input[name="form.buttons.cancel"]')
.css('display', 'inline');
/* Show the reply layer with a slide down effect */
reply_div.slideDown("slow");
reply_div.slideDown('slow');
/* Show the cancel button in the reply-to-comment form */
cancel_reply_button.css("display", "inline");
cancel_reply_button.css('display', 'inline');
};
@ -74,10 +95,10 @@
* to the function.
**************************************************************************/
$.clearForm = function (form_div) {
form_div.find(".error").removeClass("error");
form_div.find(".fieldErrorBox").remove();
form_div.find("input[type='text']").attr("value", "");
form_div.find("textarea").attr("value", "");
form_div.find('.error').removeClass('error');
form_div.find('.fieldErrorBox').remove();
form_div.find('input[type="text"]').attr('value', '');
form_div.find('textarea').attr('value', '');
/* XXX: Clean all additional form extender fields. */
};
@ -92,50 +113,50 @@
/**********************************************************************
* If the user has hit the reply button of a reply-to-comment form
* (form was submitted with a value for the "in_reply_to" field in the
* (form was submitted with a value for the 'in_reply_to' field in the
* request), create a reply-to-comment form right under this comment.
**********************************************************************/
var post_comment_div = $("#commenting");
var post_comment_div = $('#commenting');
var in_reply_to_field =
post_comment_div.find("input[name='form.widgets.in_reply_to']");
if (in_reply_to_field.val() !== "") {
var current_reply_id = "#" + in_reply_to_field.val();
var current_reply_to_div = $(".discussion").find(current_reply_id);
post_comment_div.find('input[name="form.widgets.in_reply_to"]');
if (in_reply_to_field.length !== 0 && in_reply_to_field.val() !== '') {
var current_reply_id = '#' + in_reply_to_field.val();
var current_reply_to_div = $('.discussion').find(current_reply_id);
$.createReplyForm(current_reply_to_div);
$.clearForm(post_comment_div);
}
/**********************************************************************
* If the user hits the "reply" button of an existing comment, create a
* If the user hits the 'reply' button of an existing comment, create a
* reply form right beneath this comment.
**********************************************************************/
$(".reply-to-comment-button").bind("click", function (e) {
var comment_div = $(this).parents().filter(".comment");
$('.reply-to-comment-button').bind('click', function (e) { // jshint ignore:line
var comment_div = $(this).parents().filter('.comment');
$.createReplyForm(comment_div);
$.clearForm(comment_div);
});
/**********************************************************************
* If the user hits the "clear" button of an open reply-to-comment form,
* remove the form and show the "reply" button again.
* If the user hits the 'clear' button of an open reply-to-comment form,
* remove the form and show the 'reply' button again.
**********************************************************************/
$("#commenting #form-buttons-cancel").bind("click", function (e) {
$('#commenting #form-buttons-cancel').bind('click', function (e) {
e.preventDefault();
var reply_to_comment_button = $(this).
parents().
filter(".comment").
find(".reply-to-comment-button");
filter('.comment').
find('.reply-to-comment-button');
/* Find the reply-to-comment form and hide and remove it again. */
$.reply_to_comment_form = $(this).parents().filter(".reply");
$.reply_to_comment_form.slideUp("slow", function () {
$.reply_to_comment_form = $(this).parents().filter('.reply');
$.reply_to_comment_form.slideUp('slow', function () {
$(this).remove();
});
/* Show the reply-to-comment button again. */
reply_to_comment_button.css("display", "inline");
reply_to_comment_button.css('display', 'inline');
});
@ -143,62 +164,75 @@
/**********************************************************************
* Publish a single comment.
**********************************************************************/
$("input[name='form.button.PublishComment']").live('click', function () {
$('input[name="form.button.PublishComment"]').on('click', function () {
var trigger = this;
var form = $(this).parents("form");
var form = $(this).parents('form');
var data = $(form).serialize();
var form_url = $(form).attr("action");
var form_url = $(form).attr('action');
$.ajax({
type: "GET",
type: 'GET',
url: form_url,
data: "workflow_action=publish",
data: data,
context: trigger,
success: function (msg) {
success: function (msg) { // jshint ignore:line
// remove button (trigger object can't be directly removed)
form.find("input[name='form.button.PublishComment']").remove();
form.parents(".state-pending").toggleClass('state-pending').toggleClass('state-published');
form.find('input[name="form.button.PublishComment"]').remove();
form.parents('.state-pending').toggleClass('state-pending').toggleClass('state-published');
},
error: function (msg) {
error: function (msg) { // jshint ignore:line
return true;
}
});
return false;
});
/**********************************************************************
* Edit a comment
**********************************************************************/
$('form[name="edit"]').prepOverlay({
cssclass: 'overlay-edit-comment',
width: '60%',
subtype: 'ajax',
filter: '#content>*'
});
/**********************************************************************
* Delete a comment and its answers.
**********************************************************************/
$("input[name='form.button.DeleteComment']").live('click', function () {
$('input[name="form.button.DeleteComment"]').on('click', function () {
var trigger = this;
var form = $(this).parents("form");
var form = $(this).parents('form');
var data = $(form).serialize();
var form_url = $(form).attr("action");
var form_url = $(form).attr('action');
$.ajax({
type: 'POST',
url: form_url,
context: $(trigger).parents(".comment"),
success: function (data) {
data: data,
context: $(trigger).parents('.comment'),
success: function (data) { // jshint ignore:line
var comment = $(this);
var clss = comment.attr('class');
// remove replies
var treelevel = parseInt(clss[clss.indexOf('replyTreeLevel') + 'replyTreeLevel'.length], 10);
// selector for all the following elements of lower level
var selector = ".replyTreeLevel" + treelevel;
var selector = '.replyTreeLevel' + treelevel;
for (var i = 0; i < treelevel; i++) {
selector += ", .replyTreeLevel" + i;
selector += ', .replyTreeLevel' + i;
}
comment.nextUntil(selector).each(function () {
$(this).fadeOut('fast', function () {
$(this).remove();
});
});
// Add delete button to the parent
var parent = comment.prev('[class*="replyTreeLevel' + (treelevel - 1) + '"]');
parent.find('form[name="delete"]').css('display', 'inline');
// remove comment
$(this).fadeOut('fast', function () {
$(this).remove();
});
},
error: function (req, error) {
error: function (req, error) { // jshint ignore:line
return true;
}
});
@ -210,10 +244,10 @@
* By default, hide the reply and the cancel button for the regular add
* comment form.
**********************************************************************/
$(".reply").find("input[name='form.buttons.reply']")
.css("display", "none");
$(".reply").find("input[name='form.buttons.cancel']")
.css("display", "none");
$('.reply').find('input[name="form.buttons.reply"]')
.css('display', 'none');
$('.reply').find('input[name="form.buttons.cancel"]')
.css('display', 'none');
/**********************************************************************
@ -221,11 +255,11 @@
* Otherwise hide it, since the reply functions only work with JS
* enabled.
**********************************************************************/
$(".reply-to-comment-button").css("display" , "inline");
$('.reply-to-comment-button').css('display' , 'inline');
});
//#JSCOVERAGE_ENDIF
}(jQuery));
});

View File

@ -3,7 +3,19 @@
* jQuery functions for the plone.app.discussion comment viewlet and form.
*
******************************************************************************/
(function ($) {
/* global require */
if(require === undefined){
require = function(reqs, torun){ // jshint ignore:line
'use strict';
return torun(window.jQuery);
};
}
require([ // jshint ignore:line
'jquery'
], function ($) {
'use strict';
// This unnamed function allows us to use $ inside of a block of code
// without permanently overwriting $.
// http://docs.jquery.com/Using_jQuery_with_Other_Libraries
@ -12,7 +24,7 @@
$.disableSettings = function (settings) {
$.each(settings, function (intIndex, setting) {
setting.addClass('unclickable');
var setting_field = $(setting).find("input,select");
var setting_field = $(setting).find('input,select');
setting_field.attr('disabled', 'disabled');
});
};
@ -21,7 +33,7 @@
$.enableSettings = function (settings) {
$.each(settings, function (intIndex, setting) {
setting.removeClass('unclickable');
var setting_field = $(setting).find("input,select");
var setting_field = $(setting).find('input,select');
setting_field.removeAttr('disabled');
});
};
@ -29,17 +41,17 @@
/* Update settings */
$.updateSettings = function () {
var globally_enabled = $("#content").hasClass("globally_enabled");
var anonymous_comments = $("#content").hasClass("anonymous_comments");
var moderation_enabled = $("#content").hasClass("moderation_enabled");
var moderation_custom = $("#content").hasClass("moderation_custom");
var invalid_mail_setup = $("#content").hasClass("invalid_mail_setup");
var globally_enabled = $('#content').hasClass('globally_enabled');
var moderation_custom = $('#content').hasClass('moderation_custom');
var invalid_mail_setup = $('#content').hasClass('invalid_mail_setup');
/* If commenting is globally disabled, disable all settings. */
if (globally_enabled === true) {
$.enableSettings([
$('#formfield-form-widgets-anonymous_comments'),
$('#formfield-form-widgets-moderation_enabled'),
$('#formfield-form-widgets-edit_comment_enabled'),
$('#formfield-form-widgets-delete_own_comment_enabled'),
$('#formfield-form-widgets-text_transform'),
$('#formfield-form-widgets-captcha'),
$('#formfield-form-widgets-show_commenter_image'),
@ -52,6 +64,8 @@
$.disableSettings([
$('#formfield-form-widgets-anonymous_comments'),
$('#formfield-form-widgets-moderation_enabled'),
$('#formfield-form-widgets-edit_comment_enabled'),
$('#formfield-form-widgets-delete_own_comment_enabled'),
$('#formfield-form-widgets-text_transform'),
$('#formfield-form-widgets-captcha'),
$('#formfield-form-widgets-show_commenter_image'),
@ -94,23 +108,20 @@
* Window Load Function: Executes when complete page is fully loaded,
* including all frames,
**************************************************************************/
$(window).load(function () {
$(document).ready(function () {
// Update settings on page load
$.updateSettings();
// Set #content class and update settings afterwards
$("input,select").live("change", function (e) {
var id = $(this).attr("id");
if (id === "form-widgets-globally_enabled-0") {
if ($(this).attr("checked") === true) {
$("#content").addClass("globally_enabled");
$('#form-widgets-globally_enabled-0').on('change', function(){
if (this.checked) {
$('#content').addClass('globally_enabled');
}
else {
$("#content").removeClass("globally_enabled");
$('#content').removeClass('globally_enabled');
}
$.updateSettings();
}
});
/**********************************************************************
@ -118,12 +129,12 @@
* submitting the form. Otherwise the z3c.form will raise errors on
* the required attributes.
**********************************************************************/
$("form#DiscussionSettingsEditForm").bind("submit", function (e) {
$(this).find("input,select").removeAttr('disabled');
$('form#DiscussionSettingsEditForm').bind('submit', function () {
$(this).find('input,select').removeAttr('disabled');
});
});
//#JSCOVERAGE_ENDIF
}(jQuery));
});

View File

@ -3,8 +3,20 @@
* jQuery functions for the plone.app.discussion bulk moderation.
*
******************************************************************************/
/* global require, alert */
/* jshint quotmark: false */
(function ($) {
if(require === undefined){
require = function(reqs, torun){ // jshint ignore:line
'use strict';
return torun(window.jQuery);
};
}
require([ // jshint ignore:line
'jquery'
], function ($) {
'use strict';
// This unnamed function allows us to use $ inside of a block of code
// without permanently overwriting $.
// http://docs.jquery.com/Using_jQuery_with_Other_Libraries
@ -22,16 +34,13 @@
**********************************************************************/
$("input[name='form.button.Delete']").click(function (e) {
e.preventDefault();
var button = $(this);
var row = $(this).parent().parent();
var form = $(row).parents("form");
var path = $(row).find("[name='selected_obj_paths:list']").attr("value");
var target = path + "/@@moderate-delete-comment";
var comment_id = $(this).attr("id");
$.ajax({
type: "GET",
url: target,
success: function (msg) {
success: function (msg) { // jshint ignore:line
// fade out row
$(row).fadeOut("normal", function () {
$(this).remove();
@ -42,7 +51,7 @@
location.reload();
}
},
error: function (msg) {
error: function (msg) { // jshint ignore:line
alert("Error sending AJAX request:" + target);
}
});
@ -54,15 +63,13 @@
**********************************************************************/
$("input[name='form.button.Publish']").click(function (e) {
e.preventDefault();
var button = $(this);
var row = $(this).parent().parent();
var form = $(row).parents("form");
var path = $(row).find("[name='selected_obj_paths:list']").attr("value");
var target = path + "/@@moderate-publish-comment";
$.ajax({
type: "GET",
url: target,
success: function (msg) {
success: function (msg) { // jshint ignore:line
// fade out row
$(row).fadeOut("normal", function () {
$(this).remove();
@ -73,7 +80,7 @@
location.reload();
}
},
error: function (msg) {
error: function (msg) { // jshint ignore:line
alert("Error sending AJAX request:" + target);
}
});
@ -98,7 +105,7 @@
alert("You haven't selected any comment for this bulk action." +
"Please select at least one comment.");
} else {
$.post(target, params, function (data) {
$.post(target, params, function (data) { // jshint ignore:line
valArray.each(function () {
/* Remove all selected lines. */
var row = $(this).parent().parent();
@ -151,7 +158,7 @@
// show full text
td.replaceWith("<td>" + data + "</td>");
},
error: function (msg) {
error: function (msg) { // jshint ignore:line
alert("Error getting full comment text:" + target);
}
});
@ -161,4 +168,4 @@
//#JSCOVERAGE_ENDIF
}(jQuery));
});

View File

@ -70,6 +70,7 @@ class View(BrowserView):
workflow = context.portal_workflow
oldchain = workflow.getChainForPortalType('Discussion Item')
new_workflow = workflow.comment_review_workflow
mt = getToolByName(self.context, 'portal_membership')
if type(oldchain) == TupleType and len(oldchain) > 0:
oldchain = oldchain[0]
@ -89,7 +90,6 @@ class View(BrowserView):
new_in_reply_to = None
if should_migrate:
# create a reply object
comment = CommentFactory()
comment.title = reply.Title()
@ -97,9 +97,30 @@ class View(BrowserView):
comment.mime_type = 'text/html'
comment.creator = reply.Creator()
email = reply.getProperty('email', None)
if email:
comment.author_email = email
try:
comment.author_username = reply.author_username
except AttributeError:
comment.author_username = reply.Creator()
member = mt.getMemberById(comment.author_username)
if member:
comment.author_name = member.fullname
if not comment.author_name:
# In migrated site member.fullname = ''
# while member.getProperty('fullname') has the
# correct value
if member:
comment.author_name = member.getProperty(
'fullname'
)
else:
comment.author_name = comment.author_username
try:
comment.author_email = reply.email
except AttributeError:
comment.author_email = None
comment.creation_date = DT2dt(reply.creation_date)
comment.modification_date = DT2dt(reply.modification_date)
@ -121,9 +142,10 @@ class View(BrowserView):
'action': None,
'actor': None,
'comment': 'Migrated workflow state',
'review_state': old_status.get(
'review_state': old_status and old_status.get(
'review_state',
new_workflow.initial_state),
new_workflow.initial_state
) or 'published',
'time': DateTime()
}
workflow.setStatusOf('comment_review_workflow',
@ -168,13 +190,17 @@ class View(BrowserView):
object_provides='Products.CMFCore.interfaces._content.IContentish')
log("Found %s content objects." % len(brains))
count_discussion_items = len(catalog.searchResults(
Type='Discussion Item'))
count_comments_pad = len(catalog.searchResults(
object_provides=IComment.__identifier__))
count_comments_old = len(catalog.searchResults(
object_provides=IDiscussionResponse.\
__identifier__))
count_discussion_items = len(
catalog.searchResults(Type='Discussion Item')
)
count_comments_pad = len(
catalog.searchResults(object_provides=IComment.__identifier__)
)
count_comments_old = len(
catalog.searchResults(
object_provides=IDiscussionResponse.__identifier__
)
)
log("Found %s Discussion Item objects." % count_discussion_items)
log("Found %s old discussion items." % count_comments_old)
@ -207,10 +233,14 @@ class View(BrowserView):
obj.talkback = None
if self.total_comments_deleted != self.total_comments_migrated:
log("Something went wrong during migration. The number of \
migrated comments (%s) differs from the number of deleted \
comments (%s)." # pragma: no cover
% (self.total_comments_migrated, self.total_comments_deleted))
log(
"Something went wrong during migration. The number of " +
"migrated comments (%s) differs from the number of deleted " +
"comments (%s)." % (
self.total_comments_migrated,
self.total_comments_deleted
)
)
if not test: # pragma: no cover
transaction.abort() # pragma: no cover
log("Abort transaction") # pragma: no cover
@ -223,9 +253,11 @@ class View(BrowserView):
% (self.total_comments_migrated, count_comments_old))
if self.total_comments_migrated != count_comments_old:
log("%s comments could not be migrated." %
(count_comments_old - \
self.total_comments_migrated)) # pragma: no cover
log(
"%s comments could not be migrated." % (
count_comments_old - self.total_comments_migrated
)
) # pragma: no cover
log("Please make sure your " +
"portal catalog is up-to-date.") # pragma: no cover

View File

@ -25,18 +25,18 @@
Moderate comments
</h1>
<dl class="portalMessage warning"
<div class="portalMessage warning"
tal:condition="not: view/moderation_enabled">
<dt i18n:domain="plone" i18n:translate="">Warning</dt>
<dd i18n:translate="message_moderation_disabled">
<strong i18n:domain="plone" i18n:translate="">Warning</strong>
<span tal:omit-tag="" i18n:translate="message_moderation_disabled">
Moderation workflow is disabled. You have to
<a i18n:name="enable_comment_workflow"
i18n:translate="message_enable_comment_workflow" href=""
tal:attributes="href string:${context/portal_url}/@@types-controlpanel?type_id=Discussion Item">
enable the 'Comment Review Workflow' for the Comment content
type</a> before you can moderate comments here.
</dd>
</dl>
</span>
</div>
<form tal:condition="not:items">
<fieldset id="fieldset-moderate-comments" class="formPanel">

View File

@ -1,5 +1,9 @@
# -*- coding: utf-8 -*-
from Acquisition import aq_inner, aq_parent
from AccessControl import getSecurityManager
from zope.component import queryUtility
from AccessControl import Unauthorized, getSecurityManager
from Products.Five.browser import BrowserView
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
@ -8,8 +12,11 @@ from Products.CMFCore.utils import getToolByName
from Products.statusmessages.interfaces import IStatusMessage
from plone.registry.interfaces import IRegistry
from plone.app.discussion.interfaces import IDiscussionSettings
from plone.app.discussion.interfaces import _
from plone.app.discussion.interfaces import IComment
from plone.app.discussion.interfaces import IReplies
class View(BrowserView):
@ -94,7 +101,12 @@ class DeleteComment(BrowserView):
comment = aq_inner(self.context)
conversation = aq_parent(comment)
content_object = aq_parent(conversation)
# conditional security
# base ZCML condition zope2.deleteObject allows 'delete own object'
# modify this for 'delete_own_comment_allowed' controlpanel setting
if self.can_delete(comment):
del conversation[comment.id]
content_object.reindexObject()
IStatusMessage(self.context.REQUEST).addStatusMessage(
_("Comment deleted."),
type="info")
@ -104,6 +116,42 @@ class DeleteComment(BrowserView):
came_from = content_object.absolute_url()
return self.context.REQUEST.RESPONSE.redirect(came_from)
def can_delete(self, reply):
"""Returns true if current user has the 'Delete comments'
permission.
"""
return getSecurityManager().checkPermission('Delete comments',
aq_inner(reply))
class DeleteOwnComment(DeleteComment):
"""Delete an own comment if it has no replies. Following conditions have to be true
for a user to be able to delete his comments:
* "Delete own comments" permission
* no replies to the comment
* Owner role directly assigned on the comment object
"""
def could_delete(self, comment=None):
"""Returns true if the comment could be deleted if it had no replies."""
sm = getSecurityManager()
comment = comment or aq_inner(self.context)
userid = sm.getUser().getId()
return (sm.checkPermission('Delete own comments',
comment)
and 'Owner' in comment.get_local_roles_for_userid(userid))
def can_delete(self, comment=None):
comment = comment or self.context
return (len(IReplies(aq_inner(comment))) == 0
and self.could_delete(comment=comment))
def __call__(self):
if self.can_delete():
super(DeleteOwnComment, self).__call__()
else:
raise Unauthorized("You're not allowed to delete this comment.")
class PublishComment(BrowserView):
"""Publish a comment.
@ -130,11 +178,10 @@ class PublishComment(BrowserView):
comment = aq_inner(self.context)
content_object = aq_parent(aq_parent(comment))
workflowTool = getToolByName(comment, 'portal_workflow', None)
current_state = workflowTool.getInfoFor(comment, 'review_state')
if current_state != 'published':
workflowTool.doActionFor(comment, 'publish')
workflow_action = self.request.form.get('workflow_action', 'publish')
workflowTool.doActionFor(comment, workflow_action)
comment.reindexObject()
content_object.reindexObject()
content_object.reindexObject(idxs=['total_comments'])
IStatusMessage(self.context.REQUEST).addStatusMessage(
_("Comment approved."),
type="info")
@ -201,12 +248,13 @@ class BulkActionsView(BrowserView):
context = aq_inner(self.context)
for path in self.paths:
comment = context.restrictedTraverse(path)
content_object = aq_parent(aq_parent(comment))
workflowTool = getToolByName(comment, 'portal_workflow')
current_state = workflowTool.getInfoFor(comment, 'review_state')
if current_state != 'published':
workflowTool.doActionFor(comment, 'publish')
catalog = getToolByName(comment, 'portal_catalog')
catalog.reindexObject(comment)
comment.reindexObject()
content_object.reindexObject(idxs=['total_comments'])
def mark_as_spam(self):
raise NotImplementedError
@ -223,4 +271,6 @@ class BulkActionsView(BrowserView):
for path in self.paths:
comment = context.restrictedTraverse(path)
conversation = aq_parent(comment)
content_object = aq_parent(conversation)
del conversation[comment.id]
content_object.reindexObject(idxs=['total_comments'])

View File

@ -108,6 +108,9 @@
.replyTreeLevel10 {
margin-left: 10em;
}
.defaultuserimg {
border: 0;
}
/* Reply Form
@ -175,6 +178,7 @@
/* Discussion Control Panel
-------------------------------------------------------------------------- */
.template-discussion-controlpanel .unclickable,
.template-discussion-settings .unclickable {
opacity: 0.6;
filter: alpha(opacity = 50);
@ -220,3 +224,9 @@
.row .discussion label {
font-weight:bold;
}
/* editing comments */
.overlay-edit-comment textarea {
height: 10em;
}

View File

@ -32,7 +32,7 @@ except ImportError:
pass
try:
from plone.formwidget.recaptcha.validator import WrongCaptchaCode
from plone.formwidget.recaptcha.validator import WrongCaptchaCode # noqa
except ImportError:
pass

View File

@ -33,7 +33,7 @@ def total_comments(object):
if object.meta_type != 'Discussion Item':
try:
conversation = IConversation(object)
return conversation.total_comments
return conversation.total_comments()
except TypeError: # pragma: no cover
# The item is contentish but nobody
# implemented an adapter for it
@ -61,7 +61,7 @@ def commentators(object):
if object.meta_type != 'Discussion Item':
try:
conversation = IConversation(object)
return tuple(conversation.commentators.keys())
return conversation.public_commentators
except TypeError: # pragma: no cover
# The item is contentish but nobody
# implemented an adapter for it

View File

@ -9,7 +9,9 @@ from datetime import datetime
from smtplib import SMTPException
from zope.annotation.interfaces import IAnnotatable
from zope.component import getUtility
from zope.event import notify
from zope.component.factory import Factory
from zope.component import queryUtility
@ -30,17 +32,26 @@ from Products.CMFPlone.utils import safe_unicode
from OFS.Traversable import Traversable
from plone.registry.interfaces import IRegistry
from plone.app.discussion.events import CommentAddedEvent
from plone.app.discussion.events import CommentRemovedEvent
from plone.app.discussion.events import ReplyAddedEvent
from plone.app.discussion.events import ReplyRemovedEvent
from plone.app.discussion import PloneAppDiscussionMessageFactory as _
from plone.app.discussion.interfaces import IComment
from plone.app.discussion.interfaces import IConversation
from plone.app.discussion.interfaces import IDiscussionSettings
from plone.registry.interfaces import IRegistry
from Products.CMFCore.CMFCatalogAware import CatalogAware
from Products.CMFCore.CMFCatalogAware import WorkflowAware
from Products.CMFPlone.interfaces.controlpanel import IMailSchema
from OFS.role import RoleManager
from AccessControl import ClassSecurityInfo
from AccessControl.SecurityManagement import getSecurityManager
from Products.CMFCore import permissions
COMMENT_TITLE = _(
@ -50,20 +61,20 @@ COMMENT_TITLE = _(
MAIL_NOTIFICATION_MESSAGE = _(
u"mail_notification_message",
default=u"A comment on '${title}' "
"has been posted here: ${link}\n\n"
"---\n"
"${text}\n"
"---\n")
u"has been posted here: ${link}\n\n"
u"---\n"
u"${text}\n"
u"---\n")
MAIL_NOTIFICATION_MESSAGE_MODERATOR = _(
u"mail_notification_message_moderator",
default=u"A comment on '${title}' "
"has been posted here: ${link}\n\n"
"---\n"
"${text}\n"
"---\n\n"
"Approve comment:\n${link_approve}\n\n"
"Delete comment:\n${link_delete}\n")
u"has been posted here: ${link}\n\n"
u"---\n"
u"${text}\n"
u"---\n\n"
u"Approve comment:\n${link_approve}\n\n"
u"Delete comment:\n${link_delete}\n")
logger = logging.getLogger("plone.app.discussion")
@ -78,6 +89,7 @@ class Comment(CatalogAware, WorkflowAware, DynamicType, Traversable,
"""
implements(IComment)
security = ClassSecurityInfo()
meta_type = portal_type = 'Discussion Item'
# This needs to be kept in sync with types/Discussion_Item.xml title
@ -90,7 +102,7 @@ class Comment(CatalogAware, WorkflowAware, DynamicType, Traversable,
title = u""
mime_type = "text/plain"
mime_type = None
text = u""
creator = None
@ -110,6 +122,15 @@ class Comment(CatalogAware, WorkflowAware, DynamicType, Traversable,
def __init__(self):
self.creation_date = self.modification_date = datetime.utcnow()
self.mime_type = 'text/plain'
user = getSecurityManager().getUser()
if user and user.getId():
aclpath = [x for x in user.getPhysicalPath() if x]
self._owner = (aclpath, user.getId(),)
self.__ac_local_roles__ = {
user.getId(): ['Owner']
}
@property
def __name__(self):
@ -151,12 +172,13 @@ class Comment(CatalogAware, WorkflowAware, DynamicType, Traversable,
return transform.getData()
else:
logger = logging.getLogger("plone.app.discussion")
logger.error(
_(u"Transform '%s' => '%s' not available. Failed to transform comment '%s'." % (
logger.error(_(
u"Transform '%s' => '%s' not available." % (
sourceMimetype,
targetMimetype,
self.absolute_url(),
)))
targetMimetype
) +
u"Failed to transform comment '%s'." % self.absolute_url()
))
return text
def Title(self):
@ -167,8 +189,12 @@ class Comment(CatalogAware, WorkflowAware, DynamicType, Traversable,
return self.title
if not self.author_name:
author_name = translate(Message(_(u"label_anonymous",
default=u"Anonymous")))
author_name = translate(
Message(_(
u"label_anonymous",
default=u"Anonymous"
))
)
else:
author_name = self.author_name
@ -177,14 +203,16 @@ class Comment(CatalogAware, WorkflowAware, DynamicType, Traversable,
content = aq_base(self.__parent__.__parent__)
title = translate(
Message(COMMENT_TITLE,
mapping={'author_name': author_name,
mapping={'author_name': safe_unicode(author_name),
'content': safe_unicode(content.Title())}))
return title
def Creator(self):
"""The name of the person who wrote the comment.
"""
return self.creator
return self.creator or self.author_name
security.declareProtected(permissions.View, 'Type')
def Type(self):
"""The Discussion Item content type.
@ -217,15 +245,9 @@ def notify_content_object(obj, event):
"""Tell the content object when a comment is added
"""
content_obj = aq_parent(aq_parent(obj))
# set the modified date and reindex the item accordingly
# so that 304s work correctly. This means that adding a comment
# effectively counts as modifying the content type.
content_obj.setModificationDate()
content_obj.reindexObject(idxs=('total_comments',
'last_comment_date',
'commentators',
))
'commentators'))
def notify_content_object_deleted(obj, event):
"""Remove all comments of a content object when the content object has been
@ -236,6 +258,23 @@ def notify_content_object_deleted(obj, event):
while conversation:
del conversation[conversation.keys()[0]]
def notify_comment_added(obj, event):
""" Notify custom discussion events when a comment is added or replied
"""
conversation = aq_parent(obj)
context = aq_parent(conversation)
if getattr(obj, 'in_reply_to', None):
return notify(ReplyAddedEvent(context, obj))
return notify(CommentAddedEvent(context, obj))
def notify_comment_removed(obj, event):
""" Notify custom discussion events when a comment or reply is removed
"""
conversation = aq_parent(obj)
context = aq_parent(conversation)
if getattr(obj, 'in_reply_to', None):
return notify(ReplyRemovedEvent(context, obj))
return notify(CommentRemovedEvent(context, obj))
def notify_content_object_moved(obj, event):
"""Update all comments of a content object that has been moved.
@ -244,16 +283,23 @@ def notify_content_object_moved(obj, event):
or event.oldName is None or event.newName is None:
return
# This method is also called for sublocations of moved objects. We therefore can't
# assume that event.object == obj and event.{old,new}{Parent,Name} may refer to
# the actually moved object further up in the object hierarchy.
# The object is already moved at this point. so obj.getPhysicalPath retruns the new path.
# get the part of the path that was moved.
moved_path = obj.getPhysicalPath()[len(event.newParent.getPhysicalPath()) + 1:]
# This method is also called for sublocations of moved objects. We
# therefore can't assume that event.object == obj and event.
# {old,new}{Parent,Name} may refer to the actually moved object further up
# in the object hierarchy. The object is already moved at this point. so
# obj.getPhysicalPath retruns the new path get the part of the path that
# was moved.
moved_path = obj.getPhysicalPath()[
len(event.newParent.getPhysicalPath()) + 1:
]
# Remove comments at the old location from catalog
catalog = getToolByName(obj, 'portal_catalog')
old_path = '/'.join(event.oldParent.getPhysicalPath() + (event.oldName,) + moved_path)
old_path = '/'.join(
event.oldParent.getPhysicalPath() +
(event.oldName,) +
moved_path
)
brains = catalog.searchResults(dict(
path={'query': old_path},
portal_type="Discussion Item"
@ -285,9 +331,9 @@ def notify_user(obj, event):
# Get informations that are necessary to send an email
mail_host = getToolByName(obj, 'MailHost')
portal_url = getToolByName(obj, 'portal_url')
portal = portal_url.getPortalObject()
sender = portal.getProperty('email_from_address')
registry = getUtility(IRegistry)
mail_settings = registry.forInterface(IMailSchema, prefix='plone')
sender = mail_settings.email_from_address
# Check if a sender address is available
if not sender:
@ -302,8 +348,9 @@ def notify_user(obj, event):
# when he has commented multiple times.
emails = set()
for comment in conversation.getComments():
if (obj != comment and
comment.user_notification and comment.author_email):
obj_is_not_the_comment = obj != comment
valid_user_email = comment.user_notification and comment.author_email
if obj_is_not_the_comment and valid_user_email:
emails.add(comment.author_email)
if not emails:
@ -311,13 +358,17 @@ def notify_user(obj, event):
subject = translate(_(u"A comment has been posted."),
context=obj.REQUEST)
message = translate(Message(
message = translate(
Message(
MAIL_NOTIFICATION_MESSAGE,
mapping={'title': safe_unicode(content_object.title),
'link': content_object.absolute_url() +
'/view#' + obj.id,
'text': obj.text}),
context=obj.REQUEST)
mapping={
'title': safe_unicode(content_object.title),
'link': content_object.absolute_url() + '/view#' + obj.id,
'text': obj.text
}
),
context=obj.REQUEST
)
for email in emails:
# Send email
try:
@ -354,9 +405,9 @@ def notify_moderator(obj, event):
# Get informations that are necessary to send an email
mail_host = getToolByName(obj, 'MailHost')
portal_url = getToolByName(obj, 'portal_url')
portal = portal_url.getPortalObject()
sender = portal.getProperty('email_from_address')
registry = getUtility(IRegistry)
mail_settings = registry.forInterface(IMailSchema, prefix='plone')
sender = mail_settings.email_from_address
if settings.moderator_email:
mto = settings.moderator_email
@ -372,15 +423,21 @@ def notify_moderator(obj, event):
# Compose email
subject = translate(_(u"A comment has been posted."), context=obj.REQUEST)
message = translate(Message(MAIL_NOTIFICATION_MESSAGE_MODERATOR,
link_approve = obj.absolute_url() + '/@@moderate-publish-comment'
link_delete = obj.absolute_url() + '/@@moderate-delete-comment'
message = translate(
Message(
MAIL_NOTIFICATION_MESSAGE_MODERATOR,
mapping={
'title': safe_unicode(content_object.title),
'link': content_object.absolute_url() + '/view#' + obj.id,
'text': obj.text,
'link_approve': obj.absolute_url() + '/@@moderate-publish-comment',
'link_delete': obj.absolute_url() + '/@@moderate-delete-comment',
}),
context=obj.REQUEST)
'link_approve': link_approve,
'link_delete': link_delete,
}
),
context=obj.REQUEST
)
# Send email
try:

View File

@ -14,10 +14,22 @@
<include package="plone.uuid" />
<include package="plone.app.uuid" />
<include file="contentrules.zcml" />
<include file="permissions.zcml" />
<include file="notifications.zcml" />
<include file="subscribers.zcml" />
<include file="upgrades.zcml" />
<!-- load captch before browser -->
<configure zcml:condition="installed plone.formwidget.captcha">
<include package="plone.formwidget.captcha" />
</configure>
<configure zcml:condition="installed plone.formwidget.recaptcha">
<include package="plone.formwidget.recaptcha" />
</configure>
<configure zcml:condition="installed collective.z3cform.norobots">
<include package="collective.z3cform.norobots" />
</configure>
<include package=".browser" />
<i18n:registerTranslations directory="locales" />
@ -32,6 +44,27 @@
for="Products.CMFPlone.interfaces.IPloneSiteRoot"
/>
<genericsetup:upgradeStep
title="edit comments and delete own comments"
description="reload registry config to enable new fields edit_comment_enabled and delete_own_comment_enabled"
source="100"
destination="101"
handler=".upgrades.update_registry"
sortkey="1"
profile="plone.app.discussion:default"
/>
<genericsetup:upgradeStep
title="delete comments and delete own comments"
description="reload rolemap config to enable new permissions 'Delete comments' and 'Delete own comments'"
source="101"
destination="102"
handler=".upgrades.update_rolemap"
sortkey="1"
profile="plone.app.discussion:default"
/>
<!-- Monkey Patches -->
<include package="collective.monkeypatcher" />
@ -81,14 +114,6 @@
name="plone.app.discussion.vocabularies.TextTransformVocabulary"
provides="zope.schema.interfaces.IVocabularyFactory" />
<configure zcml:condition="installed plone.formwidget.captcha">
<include package="plone.formwidget.captcha" />
</configure>
<configure zcml:condition="installed plone.formwidget.recaptcha">
<include package="plone.formwidget.recaptcha" />
</configure>
<!-- Conversation indexes -->
<adapter name="total_comments" factory=".catalog.total_comments" />
<adapter name="last_comment_date" factory=".catalog.last_comment_date" />

View File

@ -0,0 +1,97 @@
""" Content rules handlers
"""
from plone.app.discussion import PloneAppDiscussionMessageFactory as _
try:
from plone.stringinterp.adapters import BaseSubstitution
except ImportError:
class BaseSubstitution(object):
""" Fallback class if plone.stringinterp is not available
"""
def __init__(self, context, **kwargs):
self.context = context
try:
from plone.app.contentrules.handlers import execute
except ImportError:
execute = lambda context, event: False
def execute_comment(event):
""" Execute comment content rules
"""
execute(event.object, event)
class CommentSubstitution(BaseSubstitution):
""" Comment string substitution
"""
def __init__(self, context, **kwargs):
super(CommentSubstitution, self).__init__(context, **kwargs)
@property
def event(self):
""" event that triggered the content rule
"""
return self.context.REQUEST.get('event')
@property
def comment(self):
""" Get changed inline comment
"""
return self.event.comment
class Id(CommentSubstitution):
""" Comment id string substitution
"""
category = _(u'Comments')
description = _(u'Comment id')
def safe_call(self):
""" Safe call
"""
return getattr(self.comment, 'comment_id', u'')
class Text(CommentSubstitution):
""" Comment text
"""
category = _(u'Comments')
description = _(u'Comment text')
def safe_call(self):
""" Safe call
"""
return getattr(self.comment, 'text', u'')
class AuthorUserName(CommentSubstitution):
""" Comment author user name string substitution
"""
category = _(u'Comments')
description = _(u'Comment author user name')
def safe_call(self):
""" Safe call
"""
return getattr(self.comment, 'author_username', u'')
class AuthorFullName(CommentSubstitution):
""" Comment author full name string substitution
"""
category = _(u'Comments')
description = _(u'Comment author full name')
def safe_call(self):
""" Safe call
"""
return getattr(self.comment, 'author_name', u'')
class AuthorEmail(CommentSubstitution):
""" Comment author email string substitution
"""
category = _(u'Comments')
description = _(u'Comment author email')
def safe_call(self):
""" Safe call
"""
return getattr(self.comment, 'author_email', u'')

View File

@ -0,0 +1,98 @@
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:zcml="http://namespaces.zope.org/zcml">
<!-- Content Rules events -->
<configure zcml:condition="installed plone.contentrules">
<interface
interface="plone.app.discussion.interfaces.ICommentAddedEvent"
type="plone.contentrules.rule.interfaces.IRuleEventType"
name="Comment added"
/>
<interface
interface="plone.app.discussion.interfaces.ICommentRemovedEvent"
type="plone.contentrules.rule.interfaces.IRuleEventType"
name="Comment removed"
/>
<interface
interface="plone.app.discussion.interfaces.IReplyAddedEvent"
type="plone.contentrules.rule.interfaces.IRuleEventType"
name="Comment reply added"
/>
<interface
interface="plone.app.discussion.interfaces.IReplyRemovedEvent"
type="plone.contentrules.rule.interfaces.IRuleEventType"
name="Comment reply removed"
/>
</configure>
<!-- Content rules subscribers -->
<configure zcml:condition="installed plone.app.contentrules">
<subscriber
for="plone.app.discussion.interfaces.ICommentAddedEvent"
handler=".contentrules.execute_comment"
/>
<subscriber
for="plone.app.discussion.interfaces.ICommentRemovedEvent"
handler=".contentrules.execute_comment"
/>
<subscriber
for="plone.app.discussion.interfaces.IReplyAddedEvent"
handler=".contentrules.execute_comment"
/>
<subscriber
for="plone.app.discussion.interfaces.IReplyRemovedEvent"
handler=".contentrules.execute_comment"
/>
</configure>
<!-- Content rules strings -->
<configure zcml:condition="installed plone.stringinterp">
<adapter
for="zope.interface.Interface"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.Id"
name="comment_id"
/>
<adapter
for="zope.interface.Interface"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.Text"
name="comment_text"
/>
<adapter
for="zope.interface.Interface"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.AuthorUserName"
name="comment_user_id"
/>
<adapter
for="zope.interface.Interface"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.AuthorFullName"
name="comment_user_fullname"
/>
<adapter
for="zope.interface.Interface"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.AuthorEmail"
name="comment_user_email"
/>
</configure>
</configure>

View File

@ -9,46 +9,36 @@ manipulate the same data structures, but provide an API for finding and
manipulating the comments directly in reply to a particular comment or at the
top level of the conversation.
"""
from AccessControl.SpecialUsers import nobody as user_nobody
from Acquisition import aq_base
from Acquisition import aq_inner
from Acquisition import aq_parent
from Acquisition import Explicit
from BTrees.LLBTree import LLSet
from BTrees.LOBTree import LOBTree
from BTrees.OIBTree import OIBTree
from OFS.event import ObjectWillBeAddedEvent
from OFS.event import ObjectWillBeRemovedEvent
from OFS.Traversable import Traversable
from Products.CMFPlone.interfaces import IHideFromBreadcrumbs
from persistent import Persistent
from plone.app.discussion.comment import Comment
from plone.app.discussion.interfaces import IConversation
from plone.app.discussion.interfaces import IReplies
from zope.annotation.interfaces import IAnnotatable
from zope.annotation.interfaces import IAnnotations
from zope.component import adapter
from zope.component import adapts
from zope.container.contained import ContainerModifiedEvent
from zope.event import notify
from zope.interface import implementer
from zope.interface import implements
from zope.lifecycleevent import ObjectAddedEvent
from zope.lifecycleevent import ObjectCreatedEvent
from zope.lifecycleevent import ObjectRemovedEvent
import time
from persistent import Persistent
from zope.interface import implements, implementer
from zope.component import adapts
from zope.component import adapter
from zope.annotation.interfaces import IAnnotations, IAnnotatable
from zope.event import notify
from Acquisition import aq_base, aq_inner, aq_parent
from Acquisition import Explicit
from OFS.Traversable import Traversable
from OFS.event import ObjectWillBeAddedEvent
from OFS.event import ObjectWillBeRemovedEvent
from zope.container.contained import ContainerModifiedEvent
from zope.lifecycleevent import ObjectCreatedEvent
from zope.lifecycleevent import ObjectAddedEvent
from zope.lifecycleevent import ObjectRemovedEvent
from BTrees.OIBTree import OIBTree
from BTrees.LOBTree import LOBTree
from BTrees.LLBTree import LLSet
from Products.CMFPlone.interfaces import IHideFromBreadcrumbs
from plone.app.discussion.interfaces import IConversation
from plone.app.discussion.interfaces import IReplies
from plone.app.discussion.comment import Comment
from AccessControl.SpecialUsers import nobody as user_nobody
ANNOTATION_KEY = 'plone.app.discussion:conversation'
@ -87,23 +77,37 @@ class Conversation(Traversable, Persistent, Explicit):
parent = aq_inner(self.__parent__)
return parent.restrictedTraverse('@@conversation_view').enabled()
@property
def total_comments(self):
public_comments = [x for x in self._comments.values() if \
user_nobody.has_permission('View', x)]
public_comments = [
x for x in self.values()
if user_nobody.has_permission('View', x)
]
return len(public_comments)
@property
def last_comment_date(self):
try:
return self._comments[self._comments.maxKey()].creation_date
except (ValueError, KeyError, AttributeError,):
# self._comments is an Instance of a btree. The keys
# are always ordered
comment_keys = self._comments.keys()
for comment_key in reversed(comment_keys):
comment = self._comments[comment_key]
if user_nobody.has_permission('View', comment):
return comment.creation_date
return None
@property
def commentators(self):
return self._commentators
@property
def public_commentators(self):
retval = set()
for comment in self._comments.values():
if not user_nobody.has_permission('View', comment):
continue
retval.add(comment.author_username)
return tuple(retval)
def objectIds(self):
return self._comments.keys()
@ -210,7 +214,11 @@ class Conversation(Traversable, Persistent, Explicit):
def __getitem__(self, key):
"""Get an item by its long key
"""
return self._comments[long(key)].__of__(self)
try:
comment_id = long(key)
except ValueError:
return
return self._comments[comment_id].__of__(self)
def __delitem__(self, key, suppress_container_modified=False):
"""Delete an item by its long key
@ -287,12 +295,12 @@ def conversationAdapterFactory(content):
"""
Adapter factory to fetch the default conversation from annotations.
"""
annotions = IAnnotations(content)
if not ANNOTATION_KEY in annotions:
annotations = IAnnotations(content)
if not ANNOTATION_KEY in annotations:
conversation = Conversation()
conversation.__parent__ = aq_base(content)
else:
conversation = annotions[ANNOTATION_KEY]
conversation = annotations[ANNOTATION_KEY]
return conversation.__of__(content)
@ -411,9 +419,11 @@ class CommentReplies(ConversationReplies):
def __init__(self, context):
self.comment = context
self.conversation = aq_parent(self.comment)
if (self.conversation is None or
not hasattr(self.conversation, '_children')):
conversation_has_no_children = not hasattr(
self.conversation,
'_children'
)
if self.conversation is None or conversation_has_no_children:
raise TypeError("This adapter doesn't know what to do with the "
"parent conversation")

View File

@ -0,0 +1,45 @@
""" Custom discussion events
"""
from zope.interface import implements
from plone.app.discussion.interfaces import IComment
from plone.app.discussion.interfaces import IDiscussionEvent
from plone.app.discussion.interfaces import ICommentAddedEvent
from plone.app.discussion.interfaces import ICommentRemovedEvent
from plone.app.discussion.interfaces import IReplyAddedEvent
from plone.app.discussion.interfaces import IReplyRemovedEvent
class DiscussionEvent(object):
""" Custom event
"""
implements(IDiscussionEvent)
def __init__(self, context, comment, **kwargs):
self.object = context
self.comment = comment
for key, value in kwargs.items():
setattr(self, key, value)
# Add event to the request to be able to access comment attributes
# in content-rules dynamic strings
request = context.REQUEST
request.set('event', self)
class CommentAddedEvent(DiscussionEvent):
""" Event to be triggered when a Comment is added
"""
implements(ICommentAddedEvent)
class CommentRemovedEvent(DiscussionEvent):
""" Event to be triggered when a Comment is removed
"""
implements(ICommentRemovedEvent)
class ReplyAddedEvent(DiscussionEvent):
""" Event to be triggered when a Comment reply is added
"""
implements(IReplyAddedEvent)
class ReplyRemovedEvent(DiscussionEvent):
""" Event to be triggered when a Comment reply is removed
"""
implements(IReplyRemovedEvent)

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2011-04-22 17:12+0000\n"
"POT-Creation-Date: 2015-03-23 08:03+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n"
"Last-Translator: Victor Fernandez de Alba <sneridagh@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -34,12 +34,7 @@ msgstr "Comentari"
msgid "Comment Review Workflow"
msgstr "Worfklow de moderació de comentaris"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment Single State Workflow"
msgstr "Workflow d'estat únic per comentaris"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment about the last transition"
msgstr "Comentari sobre la última transició"
@ -55,10 +50,6 @@ msgstr "Comentaris afegits"
msgid "Discussion"
msgstr "Comentaris"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Essentially a workflow with no transitions, but has a Published state, so portlets and applications that expect that state will continue to work."
msgstr "Essencialment un workflow sense transicions i amb un sol estat 'Publicat' per permetre que portlets i altres aplicacions que esperen la existència d'aquest estat contiuin funcionant."
#: ../profiles/default/actions.xml
msgid "Moderate comments"
msgstr "Modera comentaris"
@ -68,17 +59,14 @@ msgid "Pending"
msgstr "Pendent"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Previous transition"
msgstr "Transició anterior"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Provides access to workflow history"
msgstr "Accés a la història del workflow"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Published"
msgstr "Publicat"
@ -91,7 +79,6 @@ msgid "Submitted, pending review."
msgstr "Enviat, pendent de moderació"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "The ID of the user who performed the previous transition"
msgstr "L'identificador únic de l'usuari que va executar la transició anterior"
@ -107,16 +94,11 @@ msgstr "Número de comentaris d'aquest contingut."
msgid "Users who have commented on the item"
msgstr "Usuaris que han comentat el contingut."
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Visible to everyone, editable by the owner."
msgstr "Visible per a tots, editable per l'autor."
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "Visible to everyone, non-editable."
msgstr "Visible per a tots, no editable."
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "When the previous transition was performed"
msgstr "Quan es va executar la transició anterior"

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: plone.app.discussion\n"
"POT-Creation-Date: 2011-04-22 17:12+0000\n"
"POT-Creation-Date: 2015-03-23 08:03+0000\n"
"PO-Revision-Date: 2010-11-03 14:51+0100\n"
"Last-Translator: Radim Novotny <novotny.radim@gmail.com>\n"
"Language-Team: DMS4U <info@dms4u.cz>\n"
@ -34,12 +34,7 @@ msgstr "Komentář"
msgid "Comment Review Workflow"
msgstr "Schvalovací workflow pro komentáře"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment Single State Workflow"
msgstr "Jednoduché workflow pro komentáře"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment about the last transition"
msgstr "Poznámka k poslední transakci"
@ -55,10 +50,6 @@ msgstr "Komentář byl přidán."
msgid "Discussion"
msgstr "Komentáře"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Essentially a workflow with no transitions, but has a Published state, so portlets and applications that expect that state will continue to work."
msgstr "Jednoduché workflow bez žádných přechodů mezi stavy, pouze se stavem Zveřejněno."
#: ../profiles/default/actions.xml
msgid "Moderate comments"
msgstr "Moderovat komentáře"
@ -68,17 +59,14 @@ msgid "Pending"
msgstr "Čekající"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Previous transition"
msgstr "Předchozí přechod stavu"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Provides access to workflow history"
msgstr "Zpřístupní historii workflow"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Published"
msgstr "Zveřejněno"
@ -91,7 +79,6 @@ msgid "Submitted, pending review."
msgstr "Předáno k posouzení."
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "The ID of the user who performed the previous transition"
msgstr "ID uživatele, který způsobil předchozí změnu stavu"
@ -107,16 +94,11 @@ msgstr "Celkový počet komentářů k této položce."
msgid "Users who have commented on the item"
msgstr "Uživatelé, kteří komentovali tuto položku"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Visible to everyone, editable by the owner."
msgstr "Viditelné pro všechny, editovatelné vlastníkem položky."
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "Visible to everyone, non-editable."
msgstr "Viditelné všem, nelze editovat."
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "When the previous transition was performed"
msgstr "Kdy byla provedena poslední změna stavu"

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: plone.app.discussion\n"
"POT-Creation-Date: 2011-04-22 17:12+0000\n"
"POT-Creation-Date: 2015-03-23 08:03+0000\n"
"PO-Revision-Date: 2010-01-28 15:00+0000\n"
"Last-Translator: Anton Stonor <anton@headnet.dk>\n"
"Language-Team: Anton Stonor <anton@headnet.dk>\n"
@ -34,12 +34,7 @@ msgstr "Kommentar"
msgid "Comment Review Workflow"
msgstr "Godkendelses-workflow for kommentarer"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment Single State Workflow"
msgstr "Et-trinsworkflow for kommentarer"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment about the last transition"
msgstr "Kommentar om seneste workflow"
@ -55,10 +50,6 @@ msgstr "Kommentarer tilføjet til indholdet"
msgid "Discussion"
msgstr "Kommentering"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Essentially a workflow with no transitions, but has a Published state, so portlets and applications that expect that state will continue to work."
msgstr "Et workflow med kun 1 tilstand, nemlig publiceret."
#: ../profiles/default/actions.xml
msgid "Moderate comments"
msgstr "Moderér kommentarer"
@ -68,17 +59,14 @@ msgid "Pending"
msgstr "Afventer"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Previous transition"
msgstr "Foregående workflow-ændringer"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Provides access to workflow history"
msgstr "Giver adgang til workflow-historikken"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Published"
msgstr "Publiceret"
@ -91,7 +79,6 @@ msgid "Submitted, pending review."
msgstr "Gemt, afventer godkendelse"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "The ID of the user who performed the previous transition"
msgstr "Brugernavnet på den, der gennemført det seneste workflow-trin"
@ -107,16 +94,11 @@ msgstr "Antal kommentarer på denne side."
msgid "Users who have commented on the item"
msgstr "Brugere, der har kommenteret på denne side"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Visible to everyone, editable by the owner."
msgstr "Synlig for alle, kan redigeres af ejeren."
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "Visible to everyone, non-editable."
msgstr "Synligt for alle, kan ikke redigeres."
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "When the previous transition was performed"
msgstr "Tidspunktet for det seneste workflow-trin"

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: plone.app.discussion\n"
"POT-Creation-Date: 2011-04-22 17:12+0000\n"
"POT-Creation-Date: 2015-03-23 08:03+0000\n"
"PO-Revision-Date: 2010-03-17 16:11+0100\n"
"Last-Translator: Timo Stollenwerk <timo@zmag.de>\n"
"Language-Team: Deutsch <plone-i18n@lists.sourceforge.net>\n"
@ -16,15 +16,15 @@ msgstr ""
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "A simple review workflow for comments"
msgstr ""
msgstr "Ein einfacher redaktioneller Workflow für Kommentare"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "Approve"
msgstr ""
msgstr "Genehmigen"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "Approving the comment makes it visible to other users."
msgstr ""
msgstr "Durch die Genehmigung des Kommentars wird es für andere Benutzer sichtbar."
#: ../profiles/default/types/Discussion_Item.xml
msgid "Comment"
@ -34,12 +34,7 @@ msgstr "Kommentar"
msgid "Comment Review Workflow"
msgstr "Arbeitsablauf für moderierte Kommentare"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment Single State Workflow"
msgstr ""
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment about the last transition"
msgstr "Kommentar zum letzten Zustandsübergang"
@ -55,10 +50,6 @@ msgstr "Ein Kommentar zu einem Artikel."
msgid "Discussion"
msgstr "Kommentare"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Essentially a workflow with no transitions, but has a Published state, so portlets and applications that expect that state will continue to work."
msgstr ""
#: ../profiles/default/actions.xml
msgid "Moderate comments"
msgstr "Kommentare moderieren"
@ -68,30 +59,26 @@ msgid "Pending"
msgstr "Zur Redaktion eingereicht"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Previous transition"
msgstr "Letzter Übergang"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Provides access to workflow history"
msgstr "Erlaubt Zugang zur Historie des Arbeitsablaufs"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Published"
msgstr "Veröffentlicht"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "Reviewer approves content"
msgstr ""
msgstr "Der Redakteur genehmigt den Inhalt"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "Submitted, pending review."
msgstr "Zur Redaktion eingereicht"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "The ID of the user who performed the previous transition"
msgstr "Die ID des Benutzers welcher den vorherigen Zustandsübergang durchgeführt hat"
@ -107,16 +94,11 @@ msgstr "Anzahl der Kommentare zu diesem Artikel."
msgid "Users who have commented on the item"
msgstr "Benutzer, die den Artikel kommentiert haben"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Visible to everyone, editable by the owner."
msgstr ""
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "Visible to everyone, non-editable."
msgstr "Für alle Benutzer sichtbar, nicht editierbar"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "When the previous transition was performed"
msgstr "Wann der vorherige Übergang durchgeführt wurde"

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: plone.app.discussion\n"
"POT-Creation-Date: 2011-04-22 17:12+0000\n"
"POT-Creation-Date: 2015-03-23 08:03+0000\n"
"PO-Revision-Date: 2010-02-23 10:26+0100\n"
"Last-Translator: Yiorgis Gozadinos <ggozad@jarn.com>\n"
"Language-Team: Greek <plone-i18n@lists.sourceforge.net>\n"
@ -34,12 +34,7 @@ msgstr "Σχόλιο"
msgid "Comment Review Workflow"
msgstr "Ροή εργασίας σχολίων"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment Single State Workflow"
msgstr ""
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment about the last transition"
msgstr "Σχόλιο για την τελευταία μετάβαση"
@ -55,10 +50,6 @@ msgstr "Σχόλια που προστέθηκαν σε ένα αντικείμ
msgid "Discussion"
msgstr "Συζήτηση"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Essentially a workflow with no transitions, but has a Published state, so portlets and applications that expect that state will continue to work."
msgstr ""
#: ../profiles/default/actions.xml
msgid "Moderate comments"
msgstr "Επιθεώρηση σχολίων"
@ -68,17 +59,14 @@ msgid "Pending"
msgstr "Σε αναμονή"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Previous transition"
msgstr "Προηγούμενη μετάβαση"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Provides access to workflow history"
msgstr "Δίνει πρόσβαση στο ιστορικό της ροής εργασίας"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Published"
msgstr "Δημοσιευμένο"
@ -91,7 +79,6 @@ msgid "Submitted, pending review."
msgstr "Υποβλήθηκε, σε αναμονή επιθεώρησης"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "The ID of the user who performed the previous transition"
msgstr "Η ταυτότητα του χρήστη που εφάρμοσε την τελευταία μετάβαση"
@ -107,16 +94,11 @@ msgstr "Σύνολικός αριθμός σχολίων για το αντικ
msgid "Users who have commented on the item"
msgstr "Χρήστες που έχουν σχολιάσει το αντικείμενο"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Visible to everyone, editable by the owner."
msgstr ""
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "Visible to everyone, non-editable."
msgstr "Ορατό από όλους, μη επεξεργάσιμο"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "When the previous transition was performed"
msgstr "Πότε εφαρμόστηκε η τελευταία μετάβαση"

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2011-04-22 17:12+0000\n"
"POT-Creation-Date: 2015-03-23 08:03+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n"
"Last-Translator: Mikel Larreategi <mlarreategi@codesyntax.com>\n"
"Language-Team: Mikel Larreategi <mlarreategi@codesyntax.com>\n"
@ -34,12 +34,7 @@ msgstr "Comentario"
msgid "Comment Review Workflow"
msgstr "Worfklow de moderación de comentarios"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment Single State Workflow"
msgstr "Workflow de estado único para comentarios"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment about the last transition"
msgstr "Comentario sobre la última transición"
@ -55,10 +50,6 @@ msgstr "Comentarios añadidos"
msgid "Discussion"
msgstr "Discusión"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Essentially a workflow with no transitions, but has a Published state, so portlets and applications that expect that state will continue to work."
msgstr "Esencialmente un workflow sin transiciones, pero tiene un estado Publicado, por lo que los portlets u otras aplicaciones que esperan ese estado seguirán funcionando"
#: ../profiles/default/actions.xml
msgid "Moderate comments"
msgstr "Moderar comentarios"
@ -68,17 +59,14 @@ msgid "Pending"
msgstr "Pendiente"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Previous transition"
msgstr "Transición anterior"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Provides access to workflow history"
msgstr "Acceso a la historia del workflow"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Published"
msgstr "Publicado"
@ -91,7 +79,6 @@ msgid "Submitted, pending review."
msgstr "Enviado, pendiente de moderación"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "The ID of the user who performed the previous transition"
msgstr "El ID del usuario que ejecutó la transición anterior"
@ -107,16 +94,11 @@ msgstr "Número de comentarios de este elemento"
msgid "Users who have commented on the item"
msgstr "Usuarios que han comentado el elemento"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Visible to everyone, editable by the owner."
msgstr "Visible para todos, editable por el autor"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "Visible to everyone, non-editable."
msgstr "Visible para todos, no-editable"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "When the previous transition was performed"
msgstr "Cuándo se ejecutó la transición anterior"

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: plone.app.discussion\n"
"POT-Creation-Date: 2011-04-22 17:12+0000\n"
"POT-Creation-Date: 2015-03-23 08:03+0000\n"
"PO-Revision-Date: 2010-01-28 15:00+0000\n"
"Last-Translator: Mikel Larreategi <mlarreategi@codesyntax.com>\n"
"Language-Team: Mikel Larreategi <mlarreategi@codesyntax.com>\n"
@ -34,12 +34,7 @@ msgstr "Erantzuna"
msgid "Comment Review Workflow"
msgstr "Erantzunen Moderazio Workflowa"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment Single State Workflow"
msgstr "Erantzunen Egoera Bakarreko Workflowa"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment about the last transition"
msgstr "Azken trantsizioari buruzko iruzkina"
@ -55,10 +50,6 @@ msgstr "Elementuari gehitutako erantzunak"
msgid "Discussion"
msgstr "Eztabaida"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Essentially a workflow with no transitions, but has a Published state, so portlets and applications that expect that state will continue to work."
msgstr "Trantsiziorik ez duen workflowa, hala ere Argitaratuta egoera bat du, beraz hori espero duten portlet edo gainontzeko aplikazioek funtzionatzen jarraituko dute"
#: ../profiles/default/actions.xml
msgid "Moderate comments"
msgstr "Erantzunak moderatu"
@ -68,17 +59,14 @@ msgid "Pending"
msgstr "Moderazio kolan"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Previous transition"
msgstr "Aurreko trantsizioa"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Provides access to workflow history"
msgstr "Workflowaren historia ikus dezakezu"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Published"
msgstr "Argitaratuta"
@ -91,7 +79,6 @@ msgid "Submitted, pending review."
msgstr "Bidalita, moderazio kolan zain."
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "The ID of the user who performed the previous transition"
msgstr "Azken trantsizioa egin zuen erabiltzailearen IDa"
@ -107,16 +94,11 @@ msgstr "Elementu honen erantzun kopurua"
msgid "Users who have commented on the item"
msgstr "Elementuaren inguruan erantzuna eman duten erabiltzaileak"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Visible to everyone, editable by the owner."
msgstr "Guztiek ikusteko, jabeak aldatzeko."
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "Visible to everyone, non-editable."
msgstr "Guztiek ikusteko, ez da editagarria."
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "When the previous transition was performed"
msgstr "Aurreko trantsizioa noiz exekutatu zen."

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: plone.app.discussion\n"
"POT-Creation-Date: 2011-04-22 17:12+0000\n"
"POT-Creation-Date: 2015-03-23 08:03+0000\n"
"PO-Revision-Date: 2010-08-06 19:23+0100\n"
"Last-Translator: Vincent Fretin <vincent.fretin@gmail.com>\n"
"Language-Team: Vincent Fretin <vincent.fretin@gmail.com>\n"
@ -34,12 +34,7 @@ msgstr "Commentaire"
msgid "Comment Review Workflow"
msgstr "Workflow de modération des commentaires"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment Single State Workflow"
msgstr "Workflow commentaire à un seul état"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment about the last transition"
msgstr "Commentaire à propos de la dernière transition"
@ -55,10 +50,6 @@ msgstr "Commentaires ajoutés à un élément."
msgid "Discussion"
msgstr "Discussion"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Essentially a workflow with no transitions, but has a Published state, so portlets and applications that expect that state will continue to work."
msgstr ""
#: ../profiles/default/actions.xml
msgid "Moderate comments"
msgstr "Modération des commentaires"
@ -68,17 +59,14 @@ msgid "Pending"
msgstr "En attente"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Previous transition"
msgstr "Transition précédente"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Provides access to workflow history"
msgstr "Permet d'accéder à l'historique du workflow"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Published"
msgstr "Publié"
@ -91,7 +79,6 @@ msgid "Submitted, pending review."
msgstr "Soumis, en attente de modération."
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "The ID of the user who performed the previous transition"
msgstr "L'identifiant utilisateur qui a effectué la transition précédente"
@ -107,16 +94,11 @@ msgstr "Nombre total de commentaires pour cet élément."
msgid "Users who have commented on the item"
msgstr "Utilisateurs qui ont commenté sur cet élément"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Visible to everyone, editable by the owner."
msgstr "Visible par tout le monde, modifiable par le propriétaire."
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "Visible to everyone, non-editable."
msgstr "Visible par tout le monde, non modifiable."
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "When the previous transition was performed"
msgstr "Quand la précédente transition a été effectué"

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2011-04-22 17:12+0000\n"
"POT-Creation-Date: 2015-03-23 08:03+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -34,12 +34,7 @@ msgstr "Commento"
msgid "Comment Review Workflow"
msgstr "Workflow per revisione del commento"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment Single State Workflow"
msgstr "Workflow per commento a stato singolo"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment about the last transition"
msgstr "Commento"
@ -55,10 +50,6 @@ msgstr "Commenti aggiunti al contenuto"
msgid "Discussion"
msgstr "Commenti"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Essentially a workflow with no transitions, but has a Published state, so portlets and applications that expect that state will continue to work."
msgstr ""
#: ../profiles/default/actions.xml
msgid "Moderate comments"
msgstr "Moderazione commenti"
@ -68,17 +59,14 @@ msgid "Pending"
msgstr "In attesa"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Previous transition"
msgstr "Transizione precedente"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Provides access to workflow history"
msgstr "Fornisce accesso alla storia del workflow"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Published"
msgstr "Pubblicato"
@ -91,7 +79,6 @@ msgid "Submitted, pending review."
msgstr "Inviato, in attesa di revisione"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "The ID of the user who performed the previous transition"
msgstr "L'ID dell'utente che ha eseguito l'ultima transizione"
@ -107,16 +94,11 @@ msgstr "Numero totale di commenti per questo elemento"
msgid "Users who have commented on the item"
msgstr "Utenti che hanno commentato l'elemento"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Visible to everyone, editable by the owner."
msgstr "Visibile a tutti, modificabile dal proprietario"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "Visible to everyone, non-editable."
msgstr "Visibile a tutti, non modificabile"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "When the previous transition was performed"
msgstr "Quando l'ultima transizione è stata eseguita"

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: plone.app.discussion\n"
"POT-Creation-Date: 2011-04-22 17:12+0000\n"
"POT-Creation-Date: 2015-03-23 08:03+0000\n"
"PO-Revision-Date: 2011-04-18 13:13+0900\n"
"Last-Translator: Takeshi Yamamoto <tyam@mac.com>\n"
"Language-Team: Hanno Schlichting <hannosch@plone.org>\n"
@ -34,12 +34,7 @@ msgstr "コメント"
msgid "Comment Review Workflow"
msgstr "コメント審査ワークフロー"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment Single State Workflow"
msgstr "コメント単一状態ワークフロー"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment about the last transition"
msgstr "最後の遷移についてのコメント"
@ -55,10 +50,6 @@ msgstr "コンテンツアイテムにコメントが追加されました"
msgid "Discussion"
msgstr "議論"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Essentially a workflow with no transitions, but has a Published state, so portlets and applications that expect that state will continue to work."
msgstr "本質的に遷移のないワークフローですが、公開状態を持つので、その状態を期待するポートレットやアプリケーションが機能し続けます。"
#: ../profiles/default/actions.xml
msgid "Moderate comments"
msgstr "コメントをモデレートする"
@ -68,17 +59,14 @@ msgid "Pending"
msgstr "保留"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Previous transition"
msgstr "前の遷移"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Provides access to workflow history"
msgstr "ワークフロー履歴へのアクセスを提供する"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Published"
msgstr "公開中"
@ -91,7 +79,6 @@ msgid "Submitted, pending review."
msgstr "提出され、審査待ち"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "The ID of the user who performed the previous transition"
msgstr "前の遷移を実施したユーザのID"
@ -107,16 +94,11 @@ msgstr "このアイテムについてのコメントの合計数"
msgid "Users who have commented on the item"
msgstr "このアイテムにコメントしたユーザ"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Visible to everyone, editable by the owner."
msgstr "誰にでも見え、所有者によって編集可能"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "Visible to everyone, non-editable."
msgstr "誰にでも見え、編集不可能"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "When the previous transition was performed"
msgstr "前の遷移が実施された時"

View File

@ -1,11 +1,10 @@
msgid ""
msgstr ""
"Project-Id-Version: plone.app.discussion\n"
"POT-Creation-Date: 2011-04-22 17:12+0000\n"
"POT-Creation-Date: 2015-03-23 08:03+0000\n"
"PO-Revision-Date: 2011-09-30 16:02+0100\n"
"Last-Translator: NFG Net Facilities Group BV <support@nfg.nl>\n"
"Language-Team: Nederlands <plone-i18n@lists.sourceforge.net>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@ -14,6 +13,7 @@ msgstr ""
"Language-Name: Dutch\n"
"Preferred-Encodings: utf-8 latin1\n"
"Domain: plone\n"
"Language: \n"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "A simple review workflow for comments"
@ -35,12 +35,7 @@ msgstr "Reactie"
msgid "Comment Review Workflow"
msgstr "Reactie Review Werkstroom"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment Single State Workflow"
msgstr "Reactie Enkelvoudige Status Werkstroom"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment about the last transition"
msgstr "Reactie op de laatste transitie"
@ -56,10 +51,6 @@ msgstr "Reacties op een content item"
msgid "Discussion"
msgstr "Discussie"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Essentially a workflow with no transitions, but has a Published state, so portlets and applications that expect that state will continue to work."
msgstr "In essentie een werkstroom zonder transities, maar met een Gepubliceerd status, zodat portlets en toepassingen die een status verwachten blijven werken."
#: ../profiles/default/actions.xml
msgid "Moderate comments"
msgstr "Reacties modereren"
@ -69,17 +60,14 @@ msgid "Pending"
msgstr "In afwachting"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Previous transition"
msgstr "Vorige transitie"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Provides access to workflow history"
msgstr "Biedt toegang tot de werkstroom geschiedenis"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Published"
msgstr "Gepubliceerd"
@ -92,7 +80,6 @@ msgid "Submitted, pending review."
msgstr "Ingediend, in afwaching van herziening."
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "The ID of the user who performed the previous transition"
msgstr "Het ID van de gebruiker die de vorige transitie heeft uitgevoerd"
@ -108,16 +95,11 @@ msgstr "Totaal aantal reacties op dit item."
msgid "Users who have commented on the item"
msgstr "Gebruikers die hebben gereageerd op dit item"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Visible to everyone, editable by the owner."
msgstr "Zichtbaar voor iedereen, bewerkbaar voor de eigenaar."
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "Visible to everyone, non-editable."
msgstr "Zichtbaar voor iedereen, niet bewerkbaar."
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "When the previous transition was performed"
msgstr "Wanneer de vorige transitie werd uitgevoerd"

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2011-04-22 17:12+0000\n"
"POT-Creation-Date: 2015-03-23 08:03+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -34,12 +34,7 @@ msgstr ""
msgid "Comment Review Workflow"
msgstr ""
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment Single State Workflow"
msgstr ""
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment about the last transition"
msgstr ""
@ -55,10 +50,6 @@ msgstr ""
msgid "Discussion"
msgstr ""
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Essentially a workflow with no transitions, but has a Published state, so portlets and applications that expect that state will continue to work."
msgstr ""
#: ../profiles/default/actions.xml
msgid "Moderate comments"
msgstr ""
@ -68,17 +59,14 @@ msgid "Pending"
msgstr ""
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Previous transition"
msgstr ""
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Provides access to workflow history"
msgstr ""
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Published"
msgstr ""
@ -91,7 +79,6 @@ msgid "Submitted, pending review."
msgstr ""
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "The ID of the user who performed the previous transition"
msgstr ""
@ -107,16 +94,11 @@ msgstr ""
msgid "Users who have commented on the item"
msgstr ""
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Visible to everyone, editable by the owner."
msgstr ""
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "Visible to everyone, non-editable."
msgstr ""
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "When the previous transition was performed"
msgstr ""

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2011-04-22 17:12+0000\n"
"POT-Creation-Date: 2015-03-23 08:03+0000\n"
"PO-Revision-Date: 2011-04-14 17:38-0300\n"
"Last-Translator: Andre Nogueira <andre@simplesconsultoria.com.br>\n"
"Language-Team: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
@ -34,12 +34,7 @@ msgstr "Comentário"
msgid "Comment Review Workflow"
msgstr "Worfklow de Moderação de Comentários"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment Single State Workflow"
msgstr "Workflow de estado único para comentários"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment about the last transition"
msgstr "Comentário sobre a última transição"
@ -55,10 +50,6 @@ msgstr "Comentários adicionados a um conteúdo."
msgid "Discussion"
msgstr "Discussão"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Essentially a workflow with no transitions, but has a Published state, so portlets and applications that expect that state will continue to work."
msgstr "Essencialmente um fluxo de trabalho sem transições, mas possui um estado Publicado, para que portlets e aplicativos que esperam este estado funcionem."
#: ../profiles/default/actions.xml
msgid "Moderate comments"
msgstr "Moderar comentários"
@ -68,17 +59,14 @@ msgid "Pending"
msgstr "Pendente"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Previous transition"
msgstr "Transição anterior"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Provides access to workflow history"
msgstr "Fornece acesso ao histórico do Workflow"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Published"
msgstr "Publicado"
@ -91,7 +79,6 @@ msgid "Submitted, pending review."
msgstr "Enviado, pendente de moderação."
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "The ID of the user who performed the previous transition"
msgstr "O ID do usuário que realizou a transição anterior"
@ -107,16 +94,11 @@ msgstr "Número total de comentários deste item."
msgid "Users who have commented on the item"
msgstr "Usuários que comentáram este item"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Visible to everyone, editable by the owner."
msgstr "Visível para todos, editável pelo autor."
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "Visible to everyone, non-editable."
msgstr "Visível para todos, não editável."
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "When the previous transition was performed"
msgstr "Quando a transição anterior foi realizada"

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: plone.app.discussion\n"
"POT-Creation-Date: 2012-07-02 15:38+0000\n"
"POT-Creation-Date: 2015-03-23 08:03+0000\n"
"PO-Revision-Date: 2012-07-02 17:54+0100\n"
"Last-Translator: Radim Novotny <novotny.radim@gmail.com>\n"
"Language-Team: Hanno Schlichting <hannosch@plone.org>\n"

View File

@ -1,9 +1,9 @@
msgid ""
msgstr ""
"Project-Id-Version: plone.app.discussion\n"
"POT-Creation-Date: 2011-04-22 17:12+0000\n"
"PO-Revision-Date: 2011-08-18 14:54+0300\n"
"Last-Translator: Olha <olha.pelishok@gmail.com>\n"
"POT-Creation-Date: 2015-03-23 08:03+0000\n"
"PO-Revision-Date: 2013-04-12 14:55+0300\n"
"Last-Translator: Roman Kozlovskyi <krzroman@gmail.com>\n"
"Language-Team: Hanno Schlichting <hannosch@plone.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
@ -16,7 +16,7 @@ msgstr ""
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "A simple review workflow for comments"
msgstr ""
msgstr "Простий робочий проце для розгляду коментарів"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "Approve"
@ -32,16 +32,11 @@ msgstr "Коментар"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "Comment Review Workflow"
msgstr ""
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment Single State Workflow"
msgstr ""
msgstr "Робочий процес розгляду коментарів"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment about the last transition"
msgstr ""
msgstr "Коментар про останню зміну стану"
#: ../profiles/default/portal_atct.xml
msgid "Commentators"
@ -55,45 +50,37 @@ msgstr "Коментарі, додані до об'єкта."
msgid "Discussion"
msgstr "Коментування"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Essentially a workflow with no transitions, but has a Published state, so portlets and applications that expect that state will continue to work."
msgstr ""
#: ../profiles/default/actions.xml
msgid "Moderate comments"
msgstr ""
msgstr "Модерування коментарів"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "Pending"
msgstr "Непідтверджений"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Previous transition"
msgstr ""
msgstr "Попередня зміна стану"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Provides access to workflow history"
msgstr ""
msgstr "Надає доступ до історії робочого процесу"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Published"
msgstr "Опублікований"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "Reviewer approves content"
msgstr ""
msgstr "Рецензент затвердив зміст"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "Submitted, pending review."
msgstr "Подано на публікацію."
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "The ID of the user who performed the previous transition"
msgstr ""
msgstr "Ідентифікатор користувача який спровокував останню зміну стану"
#: ../profiles/default/portal_atct.xml
msgid "Total number of comments"
@ -107,16 +94,11 @@ msgstr "Загальне число коментарів до цього об
msgid "Users who have commented on the item"
msgstr "Користувачі, які прокоментували цей об'єкт."
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Visible to everyone, editable by the owner."
msgstr "Видимий для всіх, редагує автор."
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "Visible to everyone, non-editable."
msgstr "Видимий для всіх, не редагується."
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "When the previous transition was performed"
msgstr ""
msgstr "Коли була здійснена попередня зміна стану"

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: plone.app.discussion\n"
"POT-Creation-Date: 2011-04-22 17:12+0000\n"
"POT-Creation-Date: 2015-03-23 08:03+0000\n"
"PO-Revision-Date: 2011-08-19 12:23+0800\n"
"Last-Translator: Jian Aijun <jianaijun@gmail.com>\n"
"Language-Team: plone <plone-i18n@lists.sourceforge.net>\n"
@ -34,12 +34,7 @@ msgstr "评论"
msgid "Comment Review Workflow"
msgstr "评论审核工作流"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment Single State Workflow"
msgstr "评论单一状态工作流"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment about the last transition"
msgstr "最后状态转换的注释"
@ -55,10 +50,6 @@ msgstr "评论已添加到内容条目。"
msgid "Discussion"
msgstr "评论"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Essentially a workflow with no transitions, but has a Published state, so portlets and applications that expect that state will continue to work."
msgstr "没有状态转换的基本工作流,只有一个发布状态,所以依赖该状态的面板和应用可以继续正常工作。"
#: ../profiles/default/actions.xml
msgid "Moderate comments"
msgstr "评论审核"
@ -68,17 +59,14 @@ msgid "Pending"
msgstr "待审核"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Previous transition"
msgstr "上一步状态转换"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Provides access to workflow history"
msgstr "提供访问工作流历史记录功能"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Published"
msgstr "已发布"
@ -91,7 +79,6 @@ msgid "Submitted, pending review."
msgstr "已提交,等待审核。"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "The ID of the user who performed the previous transition"
msgstr "执行上一步状态转换的用户 ID"
@ -107,16 +94,11 @@ msgstr "此条目的评论总数。"
msgid "Users who have commented on the item"
msgstr "此条目的评论者。"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Visible to everyone, editable by the owner."
msgstr "对任何人可见,所有者可编辑。"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "Visible to everyone, non-editable."
msgstr "对任何人可见,不可编辑。"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "When the previous transition was performed"
msgstr "当上一步状态转换被执行"

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: plone.app.discussion\n"
"POT-Creation-Date: 2011-04-22 17:12+0000\n"
"POT-Creation-Date: 2015-03-23 08:03+0000\n"
"PO-Revision-Date: 2010-08-07 23:11+0800\n"
"Last-Translator: TsungWei Hu <marr.tw@gmail.com>\n"
"Language-Team: Taiwan Python User Group <plone-i18n@lists.sourceforge.net>\n"
@ -34,12 +34,7 @@ msgstr "留言"
msgid "Comment Review Workflow"
msgstr "留言審核流程"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment Single State Workflow"
msgstr "單一狀態的工作流程"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment about the last transition"
msgstr "最後狀態轉移的備註"
@ -55,10 +50,6 @@ msgstr "新增到內容項目的留言"
msgid "Discussion"
msgstr "討論"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Essentially a workflow with no transitions, but has a Published state, so portlets and applications that expect that state will continue to work."
msgstr ""
#: ../profiles/default/actions.xml
msgid "Moderate comments"
msgstr "審核留言"
@ -68,17 +59,14 @@ msgid "Pending"
msgstr "待審核"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Previous transition"
msgstr "前一個移轉狀態"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Provides access to workflow history"
msgstr "提供工作流程歷史記錄的功能"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Published"
msgstr "已發佈"
@ -91,7 +79,6 @@ msgid "Submitted, pending review."
msgstr "已送出,待審核中。"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "The ID of the user who performed the previous transition"
msgstr "執行前一個狀態移轉的使用者識別碼"
@ -107,16 +94,11 @@ msgstr "在此項目留言的總數。"
msgid "Users who have commented on the item"
msgstr "在此項目留言的使用者"
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Visible to everyone, editable by the owner."
msgstr "所有人可檢視,擁有者可編輯。"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "Visible to everyone, non-editable."
msgstr "每個人都看得到,但無法編輯。"
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "When the previous transition was performed"
msgstr "當前一個移轉動作被執行時"

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: plone.app.discussion\n"
"POT-Creation-Date: 2011-04-22 17:12+0000\n"
"POT-Creation-Date: 2015-03-23 08:03+0000\n"
"PO-Revision-Date: 2010-01-28 15:00+0000\n"
"Last-Translator: Hanno Schlichting <hannosch@plone.org>\n"
"Language-Team: Hanno Schlichting <hannosch@plone.org>\n"
@ -34,12 +34,7 @@ msgstr ""
msgid "Comment Review Workflow"
msgstr ""
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment Single State Workflow"
msgstr ""
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Comment about the last transition"
msgstr ""
@ -55,10 +50,6 @@ msgstr ""
msgid "Discussion"
msgstr ""
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Essentially a workflow with no transitions, but has a Published state, so portlets and applications that expect that state will continue to work."
msgstr ""
#: ../profiles/default/actions.xml
msgid "Moderate comments"
msgstr ""
@ -68,17 +59,14 @@ msgid "Pending"
msgstr ""
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Previous transition"
msgstr ""
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Provides access to workflow history"
msgstr ""
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Published"
msgstr ""
@ -91,7 +79,6 @@ msgid "Submitted, pending review."
msgstr ""
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "The ID of the user who performed the previous transition"
msgstr ""
@ -107,16 +94,11 @@ msgstr ""
msgid "Users who have commented on the item"
msgstr ""
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "Visible to everyone, editable by the owner."
msgstr ""
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
msgid "Visible to everyone, non-editable."
msgstr ""
#: ../profiles/default/workflows/comment_review_workflow/definition.xml
#: ../profiles/default/workflows/one_state_workflow/definition.xml
msgid "When the previous transition was performed"
msgstr ""

View File

@ -4,6 +4,7 @@
from zope.interface import Interface
from zope.interface.common.mapping import IIterableMapping
from zope.component.interfaces import IObjectEvent
from zope import schema
from plone.app.discussion import PloneAppDiscussionMessageFactory as _
@ -31,13 +32,13 @@ class IConversation(IIterableMapping):
"""
total_comments = schema.Int(
title=_(u"Total number of comments on this item"),
title=_(u"Total number of public comments on this item"),
min=0,
readonly=True,
)
last_comment_date = schema.Date(
title=_(u"Date of the most recent comment"),
title=_(u"Date of the most recent public comment"),
readonly=True,
)
@ -46,6 +47,14 @@ class IConversation(IIterableMapping):
readonly=True,
)
public_commentators = schema.Set(
title=_(
u"The set of unique commentators (usernames) of"
u" published_comments"
),
readonly=True,
)
def addComment(comment):
"""Adds a new comment to the list of comments, and returns the
comment id that was assigned. The comment_id property on the comment
@ -150,12 +159,19 @@ class IComment(Interface):
default=u"Subject"))
mime_type = schema.ASCIILine(title=_(u"MIME type"), default="text/plain")
text = schema.Text(title=_(u"label_comment",
default=u"Comment"))
text = schema.Text(
title=_(
u"label_comment",
default=u"Comment"
)
)
user_notification = schema.Bool(title=_(u"Notify me of new comments via "
"email."),
required=False)
user_notification = schema.Bool(
title=_(
u"Notify me of new comments via email."
),
required=False
)
creator = schema.TextLine(title=_(u"Username of the commenter"))
creation_date = schema.Date(title=_(u"Creation date"))
@ -165,42 +181,10 @@ class IComment(Interface):
class ICaptcha(Interface):
"""Captcha/ReCaptcha text field to extend the existing comment form.
"""
captcha = schema.TextLine(title=u"Captcha",
captcha = schema.TextLine(title=_(u"Captcha"),
required=False)
class ICommentingTool(Interface):
"""A tool that indexes all comments for usage by the management interface.
This means the management interface can still work even though we don't
index the comments in portal_catalog.
The default implementation of this interface simply defers to
portal_catalog, but a custom version of the tool can be used to provide
an alternate indexing mechanism.
"""
def indexObject(comment):
"""Indexes a comment
"""
def reindexObject(comment):
"""Reindex a comment
"""
def unindexObject(comment):
"""Removes a comment from the indexes
"""
def uniqueValuesFor(name):
"""Get unique values for FieldIndex name
"""
def searchResults(REQUEST=None, **kw):
"""Perform a search over all indexed comments.
"""
class IDiscussionSettings(Interface):
"""Global discussion settings. This describes records stored in the
configuration registry and obtainable via plone.registry.
@ -215,11 +199,13 @@ class IDiscussionSettings(Interface):
globally_enabled = schema.Bool(
title=_(u"label_globally_enabled",
default=u"Globally enable comments"),
description=_(u"help_globally_enabled",
description=_(
u"help_globally_enabled",
default=u"If selected, users are able to post comments on the "
"site. Though, you have to enable comments for "
"specific content types, folders or content objects "
"before users will be able to post comments."),
u"site. Though, you have to enable comments for "
u"specific content types, folders or content objects "
u"before users will be able to post comments."
),
required=False,
default=False,
)
@ -227,26 +213,54 @@ class IDiscussionSettings(Interface):
anonymous_comments = schema.Bool(
title=_(u"label_anonymous_comments",
default="Enable anonymous comments"),
description=_(u"help_anonymous_comments",
description=_(
u"help_anonymous_comments",
default=u"If selected, anonymous users are able to post "
"comments without loggin in. It is highly "
"recommended to use a captcha solution to prevent "
"spam if this setting is enabled."),
u"comments without loggin in. It is highly "
u"recommended to use a captcha solution to prevent "
u"spam if this setting is enabled."
),
required=False,
default=False,
)
moderation_enabled = schema.Bool(
title=_(u"label_moderation_enabled",
default="Enable comment moderation"),
description=_(u"help_moderation_enabled",
title=_(
u"label_moderation_enabled",
default="Enable comment moderation"
),
description=_(
u"help_moderation_enabled",
default=u"If selected, comments will enter a 'Pending' state "
"in which they are invisible to the public. A user "
"with the 'Review comments' permission ('Reviewer' "
"or 'Manager') can approve comments to make them "
"visible to the public. If you want to enable a "
"custom comment workflow, you have to go to the "
"types control panel."),
u"in which they are invisible to the public. A user "
u"with the 'Review comments' permission ('Reviewer' "
u"or 'Manager') can approve comments to make them "
u"visible to the public. If you want to enable a "
u"custom comment workflow, you have to go to the "
u"types control panel."
),
required=False,
default=False,
)
edit_comment_enabled = schema.Bool(
title=_(u"label_edit_comment_enabled",
default="Enable editing of comments"),
description=_(u"help_edit_comment_enabled",
default=u"If selected, supports editing "
"of comments for users with the 'Edit comments' "
"permission."),
required=False,
default=False,
)
delete_own_comment_enabled = schema.Bool(
title=_(u"label_delete_own_comment_enabled",
default="Enable deleting own comments"),
description=_(u"help_delete_own_comment_enabled",
default=u"If selected, supports deleting "
"of own comments for users with the "
"'Delete own comments' permission."),
required=False,
default=False,
)
@ -254,14 +268,15 @@ class IDiscussionSettings(Interface):
text_transform = schema.Choice(
title=_(u"label_text_transform",
default="Comment text transform"),
description=_(u"help_text_transform",
description=_(
u"help_text_transform",
default=u"Use this setting to choose if the comment text " +
"should be transformed in any way. You can choose "
"between 'Plain text' and 'Intelligent text'. " +
"'Intelligent text' converts plain text into HTML " +
"where line breaks and indentation is preserved, " +
"and web and email addresses are made into " +
"clickable links."),
u"should be transformed in any way. You can choose "
u"between 'Plain text' and 'Intelligent text'. " +
u"'Intelligent text' converts plain text into HTML " +
u"where line breaks and indentation is preserved, " +
u"and web and email addresses are made into " +
u"clickable links."),
required=True,
default='text/plain',
vocabulary='plone.app.discussion.vocabularies.TextTransformVocabulary',
@ -270,13 +285,14 @@ class IDiscussionSettings(Interface):
captcha = schema.Choice(
title=_(u"label_captcha",
default="Captcha"),
description=_(u"help_captcha",
description=_(
u"help_captcha",
default=u"Use this setting to enable or disable Captcha "
"validation for comments. Install "
"plone.formwidget.captcha, "
"plone.formwidget.recaptcha, collective.akismet, or "
"collective.z3cform.norobots if there are no options "
"available."),
u"validation for comments. Install "
u"plone.formwidget.captcha, "
u"plone.formwidget.recaptcha, collective.akismet, or "
u"collective.z3cform.norobots if there are no options "
u"available."),
required=True,
default='disabled',
vocabulary='plone.app.discussion.vocabularies.CaptchaVocabulary',
@ -285,9 +301,10 @@ class IDiscussionSettings(Interface):
show_commenter_image = schema.Bool(
title=_(u"label_show_commenter_image",
default=u"Show commenter image"),
description=_(u"help_show_commenter_image",
description=_(
u"help_show_commenter_image",
default=u"If selected, an image of the user is shown next to "
"the comment."),
u"the comment."),
required=False,
default=True,
)
@ -295,30 +312,47 @@ class IDiscussionSettings(Interface):
moderator_notification_enabled = schema.Bool(
title=_(u"label_moderator_notification_enabled",
default=u"Enable moderator email notification"),
description=_(u"help_moderator_notification_enabled",
description=_(
u"help_moderator_notification_enabled",
default=u"If selected, the moderator is notified if a comment "
"needs attention. The moderator email address can " +
"be found in the 'Mail settings' control panel "
"(Site 'From' address)"),
u"needs attention. The moderator email address can " +
u"be set below."),
required=False,
default=False,
)
moderator_email = schema.ASCIILine(
title=_(u'label_moderator_email',
default=u'Moderator Email Address'),
description=_(u'help_moderator_email',
title=_(
u'label_moderator_email',
default=u'Moderator Email Address'
),
description=_(
u'help_moderator_email',
default=u"Address to which moderator notifications "
u"will be sent."),
required=False,
)
user_notification_enabled = schema.Bool(
title=_(u"label_user_notification_enabled",
default=u"Enable user email notification"),
description=_(u"help_user_notification_enabled",
title=_(
u"label_user_notification_enabled",
default=u"Enable user email notification"
),
description=_(
u"help_user_notification_enabled",
default=u"If selected, users can choose to be notified "
"of new comments by email."),
u"of new comments by email."),
required=False,
default=False
)
anonymous_email_enabled = schema.Bool(
title=_(u"label_anonymous_email_enabled",
default=u"Enable anonymous email field"),
description=_(
u"help_anonymous_email_enabled",
default=u"If selected, anonymous user will have to "
u"give their email."),
required=False,
default=False)
@ -326,3 +360,35 @@ class IDiscussionSettings(Interface):
class IDiscussionLayer(Interface):
"""Request marker installed via browserlayer.xml.
"""
class ICommentingTool(Interface):
"""For backwards-compatibility.
This can be removed once we no longer support upgrading from versions
of Plone that had a portal_discussion tool.
"""
#
# Custom events
#
class IDiscussionEvent(IObjectEvent):
""" Discussion custom event
"""
class ICommentAddedEvent(IDiscussionEvent):
""" Comment added
"""
class ICommentRemovedEvent(IDiscussionEvent):
""" Comment removed
"""
class IReplyAddedEvent(IDiscussionEvent):
""" Comment reply added
"""
class IReplyRemovedEvent(IDiscussionEvent):
""" Comment reply removed
"""

View File

@ -33,103 +33,127 @@ msgstr ""
"Preferred-Encodings: utf-8 latin1\n"
"Domain: plone.app.discussion\n"
#: ../comment.py:264
#: ../comment.py:359
msgid "A comment has been posted."
msgstr "'n Opmerking is geplaas."
#: ../interfaces.py:257
#: ../interfaces.py:144
msgid "A comment id unique to this conversation"
msgstr "'n ID uniek tot hierdie gesprek"
#: ../browser/comments.py:67
#: ../browser/comments.py:72
msgid "Add a comment"
msgstr "Voeg 'n opmerking by"
#: ../browser/controlpanel.py:62
#: ../browser/controlpanel.py:75
msgid "Anonymous Comments"
msgstr "Anonieme kommentaar"
#: ../interfaces.py:282
msgid "Author name (for display)"
msgstr "Outeur naam (om te vertoon)"
#: ../browser/comments.py:248
#: ../browser/controlpanel.py:80
#: ../browser/comments.py:275
#: ../browser/controlpanel.py:93
msgid "Cancel"
msgstr "Kanselleer"
#: ../browser/controlpanel.py:76
#: ../interfaces.py:184
msgid "Captcha"
msgstr ""
#: ../browser/controlpanel.py:89
msgid "Changes saved"
msgstr ""
#: ../browser/moderation.py:133
#: ../browser/moderation.py:186
msgid "Comment approved."
msgstr "Opmerking goedgekeur"
#: ../browser/moderation.py:94
#: ../contentrules.py:92
msgid "Comment author email"
msgstr ""
#: ../contentrules.py:81
msgid "Comment author full name"
msgstr ""
#: ../contentrules.py:70
msgid "Comment author user name"
msgstr ""
#: ../browser/moderation.py:111
msgid "Comment deleted."
msgstr "Opmerking verwyder"
#: ../browser/controlpanel.py:63
#: ../contentrules.py:48
msgid "Comment id"
msgstr ""
#: ../contentrules.py:59
msgid "Comment text"
msgstr ""
#: ../browser/controlpanel.py:76
msgid "Commenter Image"
msgstr "Kommentator se Profielfoto"
msgid "Commenting infrastructure for Plone"
msgstr "Kommentaarinfrastruktuur vir Plone"
#: ../interfaces.py:252
#: ../contentrules.py:47
msgid "Comments"
msgstr ""
#: ../interfaces.py:139
msgid "Conversation"
msgstr "Gesprek"
#: ../interfaces.py:283
#: ../interfaces.py:177
msgid "Creation date"
msgstr "Skeppingsdatum"
#: ../interfaces.py:162
msgid "Date of the most recent comment"
msgstr "Datum van die laaste opmerking"
#: ../interfaces.py:41
msgid "Date of the most recent public comment"
msgstr ""
#: ../vocabularies.py:44
msgid "Disabled"
msgstr "Uitgeskakel"
#: ../browser/controlpanel.py:32
#: ../browser/controlpanel.py:33
msgid "Discussion settings"
msgstr "Kommentaar instellings"
#: ../browser/controlpanel.py:82
#: ../browser/controlpanel.py:95
msgid "Edit cancelled"
msgstr ""
#: ../interfaces.py:269
#: ../interfaces.py:156
msgid "Email"
msgstr "E-pos"
#: ../browser/controlpanel.py:61
#: ../browser/controlpanel.py:74
msgid "Enable Comments"
msgstr "Laat kommentare toe"
#: ../interfaces.py:260
#: ../interfaces.py:147
msgid "Id of comment this comment is in reply to"
msgstr "Id van dié opmerking waarop hierdie een antwoord"
#: ../interfaces.py:274
#: ../interfaces.py:161
msgid "MIME type"
msgstr "MIME-tipe"
#: ../browser/controlpanel.py:65
#: ../browser/controlpanel.py:78
msgid "Moderator Email Notification"
msgstr "E-pos in kennis stelling vir die redaksie"
#: ../interfaces.py:284
#: ../interfaces.py:178
msgid "Modification date"
msgstr "Wysigingsdatum"
#: ../interfaces.py:254
#: ../interfaces.py:141
msgid "Name"
msgstr "Naam"
#: ../interfaces.py:278
#: ../interfaces.py:170
msgid "Notify me of new comments via email."
msgstr "Stel my in kennis van nuwe opmerkings m.b.v e-pos"
@ -137,32 +161,44 @@ msgstr "Stel my in kennis van nuwe opmerkings m.b.v e-pos"
msgid "Plone Discussions"
msgstr "Plone Kommentare"
#: ../interfaces.py:247
#: ../interfaces.py:134
msgid "Portal type"
msgstr "Portaaltipe"
#: ../browser/controlpanel.py:69
#: ../browser/controlpanel.py:82
msgid "Save"
msgstr ""
#: ../interfaces.py:167
#: ../interfaces.py:46
msgid "The set of unique commentators (usernames)"
msgstr "Lys van kommentators (gebruikersname)"
#: ../interfaces.py:156
msgid "Total number of comments on this item"
msgstr "Totale aantal opmerkings op hierdie item"
#: ../interfaces.py:51
msgid "The set of unique commentators (usernames) of published_comments"
msgstr ""
#: ../browser/controlpanel.py:67
#: ../interfaces.py:35
msgid "Total number of public comments on this item"
msgstr ""
#: ../comment.py:175
msgid "Transform '%s' => '%s' not available."
msgstr ""
#: ../browser/controlpanel.py:80
msgid "User Email Notification"
msgstr "Gebruik e-pos in kennis stelling"
#: ../browser/comments.py:241
#: ../interfaces.py:176
msgid "Username of the commenter"
msgstr ""
#: ../browser/comments.py:268
msgid "Your comment awaits moderator approval."
msgstr "Die opmerking sal geplaas word sodra dit goedgekeur is."
#. Default: "Comment"
#: ../browser/comments.py:123
#: ../browser/comments.py:138
msgid "add_comment_button"
msgstr "Lewer kommentaar"
@ -176,26 +212,57 @@ msgstr "Skrap"
msgid "bulkactions_publish"
msgstr "Keur goed"
#. Default: "Cancel"
#: ../browser/comment.py:97
msgid "cancel_form_button"
msgstr ""
#. Default: "You can add a comment by filling out the form below. Plain text formatting. Web and email addresses are transformed into clickable links."
#: ../browser/comments.py:52
#: ../browser/comments.py:57
msgid "comment_description_intelligent_text"
msgstr ""
#. Default: "You can add a comment by filling out the form below. Plain text formatting. You can use the Markdown syntax for links and images."
#: ../browser/comments.py:51
msgid "comment_description_markdown"
msgstr ""
#. Default: "Comments are moderated."
#: ../browser/comments.py:58
#: ../browser/comments.py:63
msgid "comment_description_moderation_enabled"
msgstr ""
#. Default: "You can add a comment by filling out the form below. Plain text formatting."
#: ../browser/comments.py:47
#: ../browser/comments.py:46
msgid "comment_description_plain_text"
msgstr ""
#. Default: "${creator} on ${content}"
#: ../comment.py:46
#. Default: "Edit comment cancelled"
#: ../browser/comment.py:101
msgid "comment_edit_cancel_notification"
msgstr ""
#. Default: "Comment was edited"
#: ../browser/comment.py:91
msgid "comment_edit_notification"
msgstr ""
#. Default: "${author_name} on ${content}"
#: ../comment.py:57
#, fuzzy
msgid "comment_title"
msgstr "${creator} op ${content}"
#. Default: "Edit comment"
#: ../browser/comment.py:70
msgid "edit_comment_form_button"
msgstr ""
#. Default: "Edit comment"
#: ../browser/comment.py:54
msgid "edit_comment_form_title"
msgstr ""
#. Default: "Action"
#: ../browser/moderation.pt:85
msgid "heading_action"
@ -227,85 +294,106 @@ msgid "heading_moderate_comments"
msgstr "Modereer kommentaar"
#. Default: "If selected, anonymous users are able to post comments without loggin in. It is highly recommended to use a captcha solution to prevent spam if this setting is enabled."
#: ../interfaces.py:38
#: ../interfaces.py:216
msgid "help_anonymous_comments"
msgstr "Indien geselekteer, sal anonieme besoekers opmerkings kan laat sonder om aan te meld. Die captcha-oplossing word aanbeveel indien hierdie opsie aangeskakel word, om gemorspos te voorkom."
#. Default: "If selected, anonymous user will have to give their email."
#: ../interfaces.py:352
msgid "help_anonymous_email_enabled"
msgstr ""
#. Default: "Use this setting to enable or disable Captcha validation for comments. Install plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet, or collective.z3cform.norobots if there are no options available."
#: ../interfaces.py:82
#: ../interfaces.py:288
msgid "help_captcha"
msgstr "Gebruik hierdie instelling om Captcha validasie vir kommentaar aan of af te skakel. Installeer plone.formwidget of plone.formwidget.captcha indien daar geen opsies beskikbaar is nie."
#. Default: "If selected, supports deleting of own comments for users with the 'Delete own comments' permission."
#: ../interfaces.py:260
msgid "help_delete_own_comment_enabled"
msgstr ""
#. Default: "Some discussion related settings are not located in the Discussion Control Panel.\nTo enable comments for a specific content type, go to the Types Control Panel of this type and choose \"Allow comments\".\nTo enable the moderation workflow for comments, go to the Types Control Panel, choose \"Comment\" and set workflow to \"Comment Review Workflow\"."
#: ../browser/controlpanel.py:33
#: ../browser/controlpanel.py:34
msgid "help_discussion_settings_editform"
msgstr ""
"Sommige besprekingsinstellings kom nie op hierdie bladsy voor nie.\n"
"Om kommentaar vir 'n spesifieke inhoudstipe aan te skakel, gaan na die Tipes Konfigurasie, kies 'Comment' en stel die werksvloei na \"Comment Review Workflow\"."
#. Default: "If selected, supports editing of comments for users with the 'Edit comments' permission."
#: ../interfaces.py:249
msgid "help_edit_comment_enabled"
msgstr ""
#. Default: "If selected, users are able to post comments on the site. Though, you have to enable comments for specific content types, folders or content objects before users will be able to post comments."
#: ../interfaces.py:26
#: ../interfaces.py:202
msgid "help_globally_enabled"
msgstr "Indien geselekteer, sal gebruikers op die werf kommentare kan plaas. Kommentare moet moontlik ook nog vir sekere inhoudstipe, vouers en objekte aangeskakel word, voordat kommentaar daar gelewer kan word."
#. Default: "If selected, comments will enter a 'Pending' state in which they are invisible to the public. A user with the 'Review comments' permission ('Reviewer' or 'Manager') can approve comments to make them visible to the public. If you want to enable a custom comment workflow, you have to go to the types control panel."
#: ../interfaces.py:50
#: ../interfaces.py:232
msgid "help_moderation_enabled"
msgstr ""
#. Default: "Address to which moderator notifications will be sent."
#: ../interfaces.py:118
#: ../interfaces.py:329
msgid "help_moderator_email"
msgstr ""
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be found in the 'Mail settings' control panel (Site 'From' address)"
#: ../interfaces.py:107
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be set below."
#: ../interfaces.py:315
#, fuzzy
msgid "help_moderator_notification_enabled"
msgstr "Indien geselekteer, sal die moderator in kennis gestel word wanneer 'n opmerking aandag verg."
#. Default: "If selected, an image of the user is shown next to the comment."
#: ../interfaces.py:97
#: ../interfaces.py:304
msgid "help_show_commenter_image"
msgstr "Indien geselekteer, sal die profielfoto van 'n gebruiker langs sy opmerking vertoon."
#. Default: "Use this setting to choose if the comment text should be transformed in any way. You can choose between 'Plain text' and 'Intelligent text'. 'Intelligent text' converts plain text into HTML where line breaks and indentation is preserved, and web and email addresses are made into clickable links."
#: ../interfaces.py:66
#: ../interfaces.py:271
msgid "help_text_transform"
msgstr ""
#. Default: "If selected, users can choose to be notified of new comments by email."
#: ../interfaces.py:127
#: ../interfaces.py:341
msgid "help_user_notification_enabled"
msgstr "Indien geselekteer, sal gebruikers kan kies om per e-pos van nuwe kommentaar in kennis gestel te word."
#. Default: "Anonymous"
#: ../comment.py:156
#: ../browser/comments.pt:75
#: ../comment.py:193
msgid "label_anonymous"
msgstr "Anoniem"
#. Default: "Enable anonymous comments"
#: ../interfaces.py:36
#: ../interfaces.py:214
msgid "label_anonymous_comments"
msgstr "Skakel anonieme kommentaar aan"
#. Default: "Enable anonymous email field"
#: ../interfaces.py:350
msgid "label_anonymous_email_enabled"
msgstr ""
#. Default: "Apply"
#: ../browser/moderation.pt:71
msgid "label_apply"
msgstr "Pas toe"
#. Default: "Captcha"
#: ../interfaces.py:80
#: ../interfaces.py:286
msgid "label_captcha"
msgstr "Captcha"
#. Default: "Comment"
#: ../interfaces.py:275
#: ../interfaces.py:163
msgid "label_comment"
msgstr "Opmerking"
#. Default: "Commenting has been disabled."
#: ../browser/comments.pt:130
#: ../browser/comments.pt:163
msgid "label_commenting_disabled"
msgstr ""
@ -314,23 +402,33 @@ msgstr ""
msgid "label_delete"
msgstr "Skrap"
#. Default: "Enable deleting own comments"
#: ../interfaces.py:258
msgid "label_delete_own_comment_enabled"
msgstr ""
#. Default: "Enable editing of comments"
#: ../interfaces.py:247
msgid "label_edit_comment_enabled"
msgstr ""
#. Default: "Globally enable comments"
#: ../interfaces.py:24
#: ../interfaces.py:200
msgid "label_globally_enabled"
msgstr "Laat kommentare globaal toe"
#. Default: "Enable comment moderation"
#: ../interfaces.py:48
#: ../interfaces.py:228
msgid "label_moderation_enabled"
msgstr ""
#. Default: "Moderator Email Address"
#: ../interfaces.py:117
#: ../interfaces.py:325
msgid "label_moderator_email"
msgstr ""
#. Default: "Enable moderator email notification"
#: ../interfaces.py:105
#: ../interfaces.py:313
msgid "label_moderator_notification_enabled"
msgstr "Skakel moderator e-pos in kennis stelling aan"
@ -340,12 +438,12 @@ msgid "label_publish"
msgstr "Keur goed"
#. Default: "says:"
#: ../browser/comments.pt:74
#: ../browser/comments.pt:78
msgid "label_says"
msgstr "sê:"
#. Default: "Show commenter image"
#: ../interfaces.py:95
#: ../interfaces.py:302
msgid "label_show_commenter_image"
msgstr "Vertoon kommentaarleweraar se foto"
@ -355,28 +453,28 @@ msgid "label_show_full_comment_text"
msgstr "Toon die volledige opmerking"
#. Default: "Subject"
#: ../interfaces.py:271
#: ../interfaces.py:158
msgid "label_subject"
msgstr "Onderwerp"
#. Default: "Comment text transform"
#: ../interfaces.py:64
#: ../interfaces.py:269
msgid "label_text_transform"
msgstr "Kommentaar tekstransformasie"
#. Default: "Enable user email notification"
#: ../interfaces.py:125
#: ../interfaces.py:337
msgid "label_user_notification_enabled"
msgstr "Skakel e-pos in kennis stelling aan vir gebruikers"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n"
#: ../comment.py:50
#: ../comment.py:61
#, fuzzy
msgid "mail_notification_message"
msgstr "'n Opmerking is op '${title}' gelewer: ${link}"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n\nApprove comment:\n${link_approve}\n\nDelete comment:\n${link_delete}\n"
#: ../comment.py:58
#: ../comment.py:69
msgid "mail_notification_message_moderator"
msgstr ""

View File

@ -2,115 +2,139 @@ msgid ""
msgstr ""
"Project-Id-Version: plone.app.discussion\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI +ZONE\n"
"PO-Revision-Date: 2010-11-17 16:52+0100\n"
"Last-Translator: Victor Fernandez de Alba <sneridagh@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"PO-Revision-Date: 2014-12-11 16:07+0100\n"
"Last-Translator: Roberto Diaz <plone.team@upcnet.es>\n"
"Language-Team: Catalan <plone-i18n@lists.sourceforge.net>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"Language-Code: ca\n"
"Language-Name: Catalan\n"
"Preferred-Encodings: utf-8 latin1\n"
"Domain: plone.app.discussion\n"
#: ../comment.py:264
#: ../comment.py:359
msgid "A comment has been posted."
msgstr "Comentari afegit."
#: ../interfaces.py:257
#: ../interfaces.py:144
msgid "A comment id unique to this conversation"
msgstr "Un identificador exclusiu assignat al comentari per aquesta conversa"
#: ../browser/comments.py:67
#: ../browser/comments.py:72
msgid "Add a comment"
msgstr "Afegir un comentari"
#: ../browser/controlpanel.py:62
#: ../browser/controlpanel.py:75
msgid "Anonymous Comments"
msgstr "Comentaris anònims"
#: ../interfaces.py:282
msgid "Author name (for display)"
msgstr "Nom de l'autor (per mostrar)"
#: ../browser/comments.py:248
#: ../browser/controlpanel.py:80
#: ../browser/comments.py:275
#: ../browser/controlpanel.py:93
msgid "Cancel"
msgstr "Cancel·la"
#: ../browser/controlpanel.py:76
msgid "Changes saved"
#: ../interfaces.py:184
msgid "Captcha"
msgstr ""
#: ../browser/moderation.py:133
#: ../browser/controlpanel.py:89
msgid "Changes saved"
msgstr "Canvis desats"
#: ../browser/moderation.py:186
msgid "Comment approved."
msgstr "Comentari aprovat."
#: ../browser/moderation.py:94
#: ../contentrules.py:92
msgid "Comment author email"
msgstr "Correu electrònic de l'autor del comentari"
#: ../contentrules.py:81
msgid "Comment author full name"
msgstr "Nom complet de l'autor del comentari"
#: ../contentrules.py:70
msgid "Comment author user name"
msgstr "Nom d'usuari de l'autor del comentari "
#: ../browser/moderation.py:111
msgid "Comment deleted."
msgstr "Comentari esborrat."
#: ../browser/controlpanel.py:63
#: ../contentrules.py:48
msgid "Comment id"
msgstr "Identificador del comentari"
#: ../contentrules.py:59
msgid "Comment text"
msgstr "Text del comentari"
#: ../browser/controlpanel.py:76
msgid "Commenter Image"
msgstr "Imatge de l'autor"
msgid "Commenting infrastructure for Plone"
msgstr "Infraestructura de comentaris per Plone"
#: ../interfaces.py:252
#: ../contentrules.py:47
msgid "Comments"
msgstr "Comentaris"
#: ../interfaces.py:139
msgid "Conversation"
msgstr "Conversa"
#: ../interfaces.py:283
#: ../interfaces.py:177
msgid "Creation date"
msgstr "Data de creació"
#: ../interfaces.py:162
msgid "Date of the most recent comment"
msgstr "Data del comentari més recent"
#: ../interfaces.py:41
msgid "Date of the most recent public comment"
msgstr "Data de l'últim comentari públic"
#: ../vocabularies.py:44
msgid "Disabled"
msgstr "Desactivat"
#: ../browser/controlpanel.py:32
#: ../browser/controlpanel.py:33
msgid "Discussion settings"
msgstr "Configuració dels comentaris"
#: ../browser/controlpanel.py:82
#: ../browser/controlpanel.py:95
msgid "Edit cancelled"
msgstr ""
msgstr "Edició cancel·lada"
#: ../interfaces.py:269
#: ../interfaces.py:156
msgid "Email"
msgstr "Correu electrònic"
#: ../browser/controlpanel.py:61
#: ../browser/controlpanel.py:74
msgid "Enable Comments"
msgstr "Permetre comentaris"
#: ../interfaces.py:260
#: ../interfaces.py:147
msgid "Id of comment this comment is in reply to"
msgstr "Identificador únic del comentari en relació al comentari del qual és resposta"
#: ../interfaces.py:274
#: ../interfaces.py:161
msgid "MIME type"
msgstr "Tipus MIME"
#: ../browser/controlpanel.py:65
#: ../browser/controlpanel.py:78
msgid "Moderator Email Notification"
msgstr "Notificació al moderador per correu electrònic"
#: ../interfaces.py:284
#: ../interfaces.py:178
msgid "Modification date"
msgstr "Data de modificació"
#: ../interfaces.py:254
#: ../interfaces.py:141
msgid "Name"
msgstr "Nom"
#: ../interfaces.py:278
#: ../interfaces.py:170
msgid "Notify me of new comments via email."
msgstr "Notifica'm de la creació de nous comentaris via correu electrònic."
@ -118,32 +142,44 @@ msgstr "Notifica'm de la creació de nous comentaris via correu electrònic."
msgid "Plone Discussions"
msgstr "Plone Discussions"
#: ../interfaces.py:247
#: ../interfaces.py:134
msgid "Portal type"
msgstr "Tipus d'objecte"
#: ../browser/controlpanel.py:69
#: ../browser/controlpanel.py:82
msgid "Save"
msgstr ""
msgstr "Desa"
#: ../interfaces.py:167
#: ../interfaces.py:46
msgid "The set of unique commentators (usernames)"
msgstr "Llistat d'usuaris que han comentat (noms d'usuari)"
#: ../interfaces.py:156
msgid "Total number of comments on this item"
msgstr "Número total de comentaris en aquest contingut"
#: ../interfaces.py:51
msgid "The set of unique commentators (usernames) of published_comments"
msgstr "El conjunt de comentaristes únics (noms d'usuari) de comentaris publicats"
#: ../browser/controlpanel.py:67
#: ../interfaces.py:35
msgid "Total number of public comments on this item"
msgstr "Nombre total de comentaris públics sobre aquest article"
#: ../comment.py:175
msgid "Transform '%s' => '%s' not available."
msgstr "Transformació de '%s' => '%s' no disponible."
#: ../browser/controlpanel.py:80
msgid "User Email Notification"
msgstr "Notificació a l'usuari via mail"
#: ../browser/comments.py:241
#: ../interfaces.py:176
msgid "Username of the commenter"
msgstr "Nom d'usuari del comentarista"
#: ../browser/comments.py:268
msgid "Your comment awaits moderator approval."
msgstr "El vostre comentari està pendent d'aprovació per part del moderador de l'espai"
#. Default: "Comment"
#: ../browser/comments.py:123
#: ../browser/comments.py:138
msgid "add_comment_button"
msgstr "Comenta"
@ -157,26 +193,56 @@ msgstr "Esborra"
msgid "bulkactions_publish"
msgstr "Publica"
#. Default: "Cancel"
#: ../browser/comment.py:97
msgid "cancel_form_button"
msgstr "Cancel·la"
#. Default: "You can add a comment by filling out the form below. Plain text formatting. Web and email addresses are transformed into clickable links."
#: ../browser/comments.py:52
#: ../browser/comments.py:57
msgid "comment_description_intelligent_text"
msgstr ""
msgstr "Podeu afegir un comentari omplint el següent formulari. Format text pla. Les adreces web y correus electrònics es converteixen a enllaços."
#. Default: "You can add a comment by filling out the form below. Plain text formatting. You can use the Markdown syntax for links and images."
#: ../browser/comments.py:51
msgid "comment_description_markdown"
msgstr "Podeu afegir un comentari omplint el següent formulari. Format text pla. Podeu utilitzar la sintaxi de Markdown per als enllaços i les imatges."
#. Default: "Comments are moderated."
#: ../browser/comments.py:58
#: ../browser/comments.py:63
msgid "comment_description_moderation_enabled"
msgstr ""
msgstr "Comentaris estàn moderats"
#. Default: "You can add a comment by filling out the form below. Plain text formatting."
#: ../browser/comments.py:47
#: ../browser/comments.py:46
msgid "comment_description_plain_text"
msgstr ""
msgstr "Podeu afegir un comentari en el següent formulari. Format text pla."
#. Default: "${creator} on ${content}"
#: ../comment.py:46
#. Default: "Edit comment cancelled"
#: ../browser/comment.py:101
msgid "comment_edit_cancel_notification"
msgstr "Edició del comentari cancel·lada"
#. Default: "Comment was edited"
#: ../browser/comment.py:91
msgid "comment_edit_notification"
msgstr "S'ha editat el comentari"
#. Default: "${author_name} on ${content}"
#: ../comment.py:57
msgid "comment_title"
msgstr "${creator} sobre ${content}"
#. Default: "Edit comment"
#: ../browser/comment.py:70
msgid "edit_comment_form_button"
msgstr "Editar comentari"
#. Default: "Edit comment"
#: ../browser/comment.py:54
msgid "edit_comment_form_title"
msgstr "Editar commentari"
#. Default: "Action"
#: ../browser/moderation.pt:85
msgid "heading_action"
@ -208,108 +274,139 @@ msgid "heading_moderate_comments"
msgstr "Moderar comentaris"
#. Default: "If selected, anonymous users are able to post comments without loggin in. It is highly recommended to use a captcha solution to prevent spam if this setting is enabled."
#: ../interfaces.py:38
#: ../interfaces.py:216
msgid "help_anonymous_comments"
msgstr "Si està seleccionada, els usuaris anònims podran afegir comentaris sense identificar-se. Es recomana la utilització de una eina de captcha per evitar comentaris spam si aquesta opció està activada."
#. Default: "If selected, anonymous user will have to give their email."
#: ../interfaces.py:352
msgid "help_anonymous_email_enabled"
msgstr "Si se selecciona, el usuari anònim haurà de donar la seva adreça de correu electrònic."
#. Default: "Use this setting to enable or disable Captcha validation for comments. Install plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet, or collective.z3cform.norobots if there are no options available."
#: ../interfaces.py:82
#: ../interfaces.py:288
msgid "help_captcha"
msgstr "Utilitzeu aquesta opció per activar o desactivar una eina de captcha pels comentaris. Instal·leu plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet o collective.z3cform.norobots si no teniu cap opció disponible."
#. Default: "If selected, supports deleting of own comments for users with the 'Delete own comments' permission."
#: ../interfaces.py:260
msgid "help_delete_own_comment_enabled"
msgstr ""
#. Default: "Some discussion related settings are not located in the Discussion Control Panel.\nTo enable comments for a specific content type, go to the Types Control Panel of this type and choose \"Allow comments\".\nTo enable the moderation workflow for comments, go to the Types Control Panel, choose \"Comment\" and set workflow to \"Comment Review Workflow\"."
#: ../browser/controlpanel.py:33
#: ../browser/controlpanel.py:34
msgid "help_discussion_settings_editform"
msgstr "Algunes de les configuracions dels comentaris no estan en la element de configuració 'Comentaris' del panell de control de l'espai. Per activar els comentaris per un tipus de contingut específic, dirigiu-vos al element de configuració 'Tipus' i activeu la opció 'Permetre comentaris'. Per activar el circuit de treball (workflow) de moderació de comentaris, dirigiu-vos al element de configuració de 'Tipus', seleccioneu 'Comentari' i escolliu el 'Workflow de moderació de comentaris'."
#. Default: "If selected, supports editing of comments for users with the 'Edit comments' permission."
#: ../interfaces.py:249
#, fuzzy
msgid "help_edit_comment_enabled"
msgstr "Si es selecciona, dóna suport a l'edició i eliminació dels comentaris dels usuaris amb el permís 'Edita comentaris'"
#. Default: "If selected, users are able to post comments on the site. Though, you have to enable comments for specific content types, folders or content objects before users will be able to post comments."
#: ../interfaces.py:26
#: ../interfaces.py:202
msgid "help_globally_enabled"
msgstr "Si està seleccionada, es permet que els usuaris puguin afegir comentaris a l'espai. De tota manera, teniu que activar els comentaris per a cada tipus de contingut específicament abans de que pogueu afegir comentaris."
#. Default: "If selected, comments will enter a 'Pending' state in which they are invisible to the public. A user with the 'Review comments' permission ('Reviewer' or 'Manager') can approve comments to make them visible to the public. If you want to enable a custom comment workflow, you have to go to the types control panel."
#: ../interfaces.py:50
#: ../interfaces.py:232
msgid "help_moderation_enabled"
msgstr ""
msgstr "Si està seleccionat, els comentaris entraran en un estat \"pendent\" en què són invisibles per al públic. Un usuari amb permís 'Review comments' ('Reviewer' o 'Manager') pot aprovar comentaris perquè siguin visibles per al públic. Si desitja habilitar un comentari personalitzada de flux de treball, vostè ha d'anar al panell de control de tipus."
#. Default: "Address to which moderator notifications will be sent."
#: ../interfaces.py:118
#: ../interfaces.py:329
msgid "help_moderator_email"
msgstr ""
msgstr "Adreça a la qual s'enviaran les notificacions de moderador."
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be found in the 'Mail settings' control panel (Site 'From' address)"
#: ../interfaces.py:107
#, fuzzy
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be set below."
#: ../interfaces.py:315
msgid "help_moderator_notification_enabled"
msgstr "Si està seleccionada, es notificarà per correu electrònic al moderador els nous comentaris."
msgstr "Si està seleccionada, es notificarà per correu electrònic al moderador, dels nous comentaris."
#. Default: "If selected, an image of the user is shown next to the comment."
#: ../interfaces.py:97
#: ../interfaces.py:304
msgid "help_show_commenter_image"
msgstr "Si està seleccionada, es mostrarà el retrat (o imatge) que hagi configurat l'usuari en el seu perfil juntament amb el comentari."
#. Default: "Use this setting to choose if the comment text should be transformed in any way. You can choose between 'Plain text' and 'Intelligent text'. 'Intelligent text' converts plain text into HTML where line breaks and indentation is preserved, and web and email addresses are made into clickable links."
#: ../interfaces.py:66
#: ../interfaces.py:271
msgid "help_text_transform"
msgstr ""
msgstr "Utilitzeu aquesta opció per escollir si el text del comentari ha de transformar-se. Pot escollir entre 'Text sense format' i 'text intel·ligent'. 'Text intel·ligent' converteix el text sense format en HTML on els salts de línia i sangria es conserven, i les adreces web i de correu electrònic es converteixen en enllaços."
#. Default: "If selected, users can choose to be notified of new comments by email."
#: ../interfaces.py:127
#: ../interfaces.py:341
msgid "help_user_notification_enabled"
msgstr "Si està seleccionada, els usuaris poden escollir si volen ser notificats cada cop que s'afegeixi un nou comentari al contingut."
#. Default: "Anonymous"
#: ../comment.py:156
#: ../browser/comments.pt:75
#: ../comment.py:193
msgid "label_anonymous"
msgstr "Anònim"
#. Default: "Enable anonymous comments"
#: ../interfaces.py:36
#: ../interfaces.py:214
msgid "label_anonymous_comments"
msgstr "Permetre comentaris anònims"
#. Default: "Enable anonymous email field"
#: ../interfaces.py:350
msgid "label_anonymous_email_enabled"
msgstr "Habilitar correu electrònic anònim"
#. Default: "Apply"
#: ../browser/moderation.pt:71
msgid "label_apply"
msgstr "Aplica"
#. Default: "Captcha"
#: ../interfaces.py:80
#: ../interfaces.py:286
msgid "label_captcha"
msgstr "Captcha"
#. Default: "Comment"
#: ../interfaces.py:275
#: ../interfaces.py:163
msgid "label_comment"
msgstr "Comentari"
#. Default: "Commenting has been disabled."
#: ../browser/comments.pt:130
#: ../browser/comments.pt:163
msgid "label_commenting_disabled"
msgstr ""
msgstr "Els comentaris s'han desactivat"
#. Default: "Delete"
#: ../browser/moderation.pt:130
msgid "label_delete"
msgstr "Esborra"
#. Default: "Enable deleting own comments"
#: ../interfaces.py:258
msgid "label_delete_own_comment_enabled"
msgstr ""
#. Default: "Enable editing of comments"
#: ../interfaces.py:247
msgid "label_edit_comment_enabled"
msgstr "Activa l'edició de comentaris"
#. Default: "Globally enable comments"
#: ../interfaces.py:24
#: ../interfaces.py:200
msgid "label_globally_enabled"
msgstr "Activa els comentaris de forma global"
#. Default: "Enable comment moderation"
#: ../interfaces.py:48
#: ../interfaces.py:228
msgid "label_moderation_enabled"
msgstr ""
msgstr "Habilitar moderació de comentaris"
#. Default: "Moderator Email Address"
#: ../interfaces.py:117
#: ../interfaces.py:325
msgid "label_moderator_email"
msgstr ""
msgstr "Correu electrònic del moderador"
#. Default: "Enable moderator email notification"
#: ../interfaces.py:105
#: ../interfaces.py:313
msgid "label_moderator_notification_enabled"
msgstr "Activa la notificació al moderador"
@ -319,12 +416,12 @@ msgid "label_publish"
msgstr "Aprova"
#. Default: "says:"
#: ../browser/comments.pt:74
#: ../browser/comments.pt:78
msgid "label_says"
msgstr "diu:"
#. Default: "Show commenter image"
#: ../interfaces.py:95
#: ../interfaces.py:302
msgid "label_show_commenter_image"
msgstr "Mostra el retrat (o imatge) de l'autor"
@ -334,30 +431,41 @@ msgid "label_show_full_comment_text"
msgstr "Mostra text complet"
#. Default: "Subject"
#: ../interfaces.py:271
#: ../interfaces.py:158
msgid "label_subject"
msgstr "Tema"
#. Default: "Comment text transform"
#: ../interfaces.py:64
#: ../interfaces.py:269
msgid "label_text_transform"
msgstr "Transformacions aplicades al text del comentari"
#. Default: "Enable user email notification"
#: ../interfaces.py:125
#: ../interfaces.py:337
msgid "label_user_notification_enabled"
msgstr "Activa les notificacions als usuaris"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n"
#: ../comment.py:50
#, fuzzy
#: ../comment.py:61
msgid "mail_notification_message"
msgstr "S'ha publicat un comentari sobre el contingut ${title} en aquesta adreça: ${link}"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n\nApprove comment:\n${link_approve}\n\nDelete comment:\n${link_delete}\n"
#: ../comment.py:58
#: ../comment.py:69
msgid "mail_notification_message_moderator"
msgstr ""
"\"Un comentari sobre '${title}' s'ha publicat aquí: ${link}\n"
"\n"
"---\n"
"${text}\n"
"---\n"
"\n"
"Aprovar comentari:\n"
"${link_approve}\n"
"\n"
"Borrar comentari:\n"
"${link_delete}\n"
"\""
#. Default: "enable the 'Comment Review Workflow' for the Comment content type"
#: ../browser/moderation.pt:33

View File

@ -14,103 +14,127 @@ msgstr ""
"Preferred-Encodings: utf-8 latin1\n"
"Domain: DOMAIN\n"
#: ../comment.py:264
#: ../comment.py:359
msgid "A comment has been posted."
msgstr "Komentář byl přidán."
#: ../interfaces.py:257
#: ../interfaces.py:144
msgid "A comment id unique to this conversation"
msgstr "Identifikátor komentáře v této konverzaci."
#: ../browser/comments.py:67
#: ../browser/comments.py:72
msgid "Add a comment"
msgstr "Přidat komentář"
#: ../browser/controlpanel.py:62
#: ../browser/controlpanel.py:75
msgid "Anonymous Comments"
msgstr "Anonymní komentáře"
#: ../interfaces.py:282
msgid "Author name (for display)"
msgstr "Jméno autora (pro zobrazení)"
#: ../browser/comments.py:248
#: ../browser/controlpanel.py:80
#: ../browser/comments.py:275
#: ../browser/controlpanel.py:93
msgid "Cancel"
msgstr "Storno"
#: ../browser/controlpanel.py:76
#: ../interfaces.py:184
msgid "Captcha"
msgstr ""
#: ../browser/controlpanel.py:89
msgid "Changes saved"
msgstr "Změny byly uloženy"
#: ../browser/moderation.py:133
#: ../browser/moderation.py:186
msgid "Comment approved."
msgstr "Komentář byl schválen."
#: ../browser/moderation.py:94
#: ../contentrules.py:92
msgid "Comment author email"
msgstr ""
#: ../contentrules.py:81
msgid "Comment author full name"
msgstr ""
#: ../contentrules.py:70
msgid "Comment author user name"
msgstr ""
#: ../browser/moderation.py:111
msgid "Comment deleted."
msgstr "Komentář byl odebrán."
#: ../browser/controlpanel.py:63
#: ../contentrules.py:48
msgid "Comment id"
msgstr ""
#: ../contentrules.py:59
msgid "Comment text"
msgstr ""
#: ../browser/controlpanel.py:76
msgid "Commenter Image"
msgstr "Portét komentujícího"
msgid "Commenting infrastructure for Plone"
msgstr "Komentářový systém pro Plone"
#: ../interfaces.py:252
#: ../contentrules.py:47
msgid "Comments"
msgstr ""
#: ../interfaces.py:139
msgid "Conversation"
msgstr "Konverzace"
#: ../interfaces.py:283
#: ../interfaces.py:177
msgid "Creation date"
msgstr "Datum vytvoření"
#: ../interfaces.py:162
msgid "Date of the most recent comment"
msgstr "Datum nejnovějšího komentáře"
#: ../interfaces.py:41
msgid "Date of the most recent public comment"
msgstr ""
#: ../vocabularies.py:44
msgid "Disabled"
msgstr "Zakázáno"
#: ../browser/controlpanel.py:32
#: ../browser/controlpanel.py:33
msgid "Discussion settings"
msgstr "Nastavení komentářů"
#: ../browser/controlpanel.py:82
#: ../browser/controlpanel.py:95
msgid "Edit cancelled"
msgstr "Úpravy byly stornovány"
#: ../interfaces.py:269
#: ../interfaces.py:156
msgid "Email"
msgstr "Email"
#: ../browser/controlpanel.py:61
#: ../browser/controlpanel.py:74
msgid "Enable Comments"
msgstr "Povolit komentáře"
#: ../interfaces.py:260
#: ../interfaces.py:147
msgid "Id of comment this comment is in reply to"
msgstr "Id předchozího komentáře, na který je tento odpovědí"
#: ../interfaces.py:274
#: ../interfaces.py:161
msgid "MIME type"
msgstr "MIME typ"
#: ../browser/controlpanel.py:65
#: ../browser/controlpanel.py:78
msgid "Moderator Email Notification"
msgstr "Notifikace moderátorů emailem"
#: ../interfaces.py:284
#: ../interfaces.py:178
msgid "Modification date"
msgstr "Datum změny"
#: ../interfaces.py:254
#: ../interfaces.py:141
msgid "Name"
msgstr "Jméno"
#: ../interfaces.py:278
#: ../interfaces.py:170
msgid "Notify me of new comments via email."
msgstr "Chci zasílat notifikace o nových komentářích emailem."
@ -118,32 +142,44 @@ msgstr "Chci zasílat notifikace o nových komentářích emailem."
msgid "Plone Discussions"
msgstr "Komentáře"
#: ../interfaces.py:247
#: ../interfaces.py:134
msgid "Portal type"
msgstr "Typ položky"
#: ../browser/controlpanel.py:69
#: ../browser/controlpanel.py:82
msgid "Save"
msgstr "Uložit"
#: ../interfaces.py:167
#: ../interfaces.py:46
msgid "The set of unique commentators (usernames)"
msgstr "Seznam komentujících"
#: ../interfaces.py:156
msgid "Total number of comments on this item"
msgstr "Celkový počet komentářů k této položce"
#: ../interfaces.py:51
msgid "The set of unique commentators (usernames) of published_comments"
msgstr ""
#: ../browser/controlpanel.py:67
#: ../interfaces.py:35
msgid "Total number of public comments on this item"
msgstr ""
#: ../comment.py:175
msgid "Transform '%s' => '%s' not available."
msgstr ""
#: ../browser/controlpanel.py:80
msgid "User Email Notification"
msgstr "Notifikace emailem"
#: ../browser/comments.py:241
#: ../interfaces.py:176
msgid "Username of the commenter"
msgstr ""
#: ../browser/comments.py:268
msgid "Your comment awaits moderator approval."
msgstr "Váš komentář čeká na schválení."
#. Default: "Comment"
#: ../browser/comments.py:123
#: ../browser/comments.py:138
msgid "add_comment_button"
msgstr "Přidat komentář"
@ -157,26 +193,57 @@ msgstr "Odebrat"
msgid "bulkactions_publish"
msgstr "Schválit"
#. Default: "Cancel"
#: ../browser/comment.py:97
msgid "cancel_form_button"
msgstr ""
#. Default: "You can add a comment by filling out the form below. Plain text formatting. Web and email addresses are transformed into clickable links."
#: ../browser/comments.py:52
#: ../browser/comments.py:57
msgid "comment_description_intelligent_text"
msgstr "Pokud chcete přidat komentář, zadejte jej do formuláře níže. Nejsou povoleny žádné formátovací značky. Adresy na web nebo emailové adresy budou automaticky transformovány na aktivní odkazy."
#. Default: "You can add a comment by filling out the form below. Plain text formatting. You can use the Markdown syntax for links and images."
#: ../browser/comments.py:51
msgid "comment_description_markdown"
msgstr ""
#. Default: "Comments are moderated."
#: ../browser/comments.py:58
#: ../browser/comments.py:63
msgid "comment_description_moderation_enabled"
msgstr "Komentáře jsou moderovány."
#. Default: "You can add a comment by filling out the form below. Plain text formatting."
#: ../browser/comments.py:47
#: ../browser/comments.py:46
msgid "comment_description_plain_text"
msgstr "Pokud chcete přidat komentář, zadejte jej do formuláře níže. Nejsou povoleny žádné formátovací značky."
#. Default: "${creator} on ${content}"
#: ../comment.py:46
#. Default: "Edit comment cancelled"
#: ../browser/comment.py:101
msgid "comment_edit_cancel_notification"
msgstr ""
#. Default: "Comment was edited"
#: ../browser/comment.py:91
msgid "comment_edit_notification"
msgstr ""
#. Default: "${author_name} on ${content}"
#: ../comment.py:57
#, fuzzy
msgid "comment_title"
msgstr "${creator} k ${content}"
#. Default: "Edit comment"
#: ../browser/comment.py:70
msgid "edit_comment_form_button"
msgstr ""
#. Default: "Edit comment"
#: ../browser/comment.py:54
msgid "edit_comment_form_title"
msgstr ""
#. Default: "Action"
#: ../browser/moderation.pt:85
msgid "heading_action"
@ -208,85 +275,107 @@ msgid "heading_moderate_comments"
msgstr "Správa komentářů"
#. Default: "If selected, anonymous users are able to post comments without loggin in. It is highly recommended to use a captcha solution to prevent spam if this setting is enabled."
#: ../interfaces.py:38
#: ../interfaces.py:216
msgid "help_anonymous_comments"
msgstr "Je-li zaškrtnuto, nepřihlášení uživatelé mohou posílat komentáře. Doporučujeme použití Captcha, pokud povolíte tuto volbu."
#. Default: "If selected, anonymous user will have to give their email."
#: ../interfaces.py:352
msgid "help_anonymous_email_enabled"
msgstr ""
#. Default: "Use this setting to enable or disable Captcha validation for comments. Install plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet, or collective.z3cform.norobots if there are no options available."
#: ../interfaces.py:82
#: ../interfaces.py:288
msgid "help_captcha"
msgstr "Zde můžete povolit nebo zakázat Captcha pro komentáře. Pokud zde není žádná možnost k výběru, nainstalujte prosím balíček plone.formwidget.captcha nebo plone.formwidget.recaptcha, collective.akismet nebo collective.z3cform.norobots."
#. Default: "If selected, supports deleting of own comments for users with the 'Delete own comments' permission."
#: ../interfaces.py:260
msgid "help_delete_own_comment_enabled"
msgstr ""
#. Default: "Some discussion related settings are not located in the Discussion Control Panel.\nTo enable comments for a specific content type, go to the Types Control Panel of this type and choose \"Allow comments\".\nTo enable the moderation workflow for comments, go to the Types Control Panel, choose \"Comment\" and set workflow to \"Comment Review Workflow\"."
#: ../browser/controlpanel.py:33
#: ../browser/controlpanel.py:34
msgid "help_discussion_settings_editform"
msgstr ""
"Nekterá nastavení pro diskuse nejsou k dispozici v ovládacím panelu komentářů.\n"
" Povolení komentářů pro konkrétní typ položek se provádí v ovládacím panelu Typy, kde zaškrtnete \"Povolit komentáře\".\n"
" Pokud chcete povolit moderování komentářů, přejděte do ovládacích panelů Typy, vyberte typ položky \"Komentář\" a nastavte workflow na \"Schvalovací workflow pro komentáře\"."
#. Default: "If selected, supports editing of comments for users with the 'Edit comments' permission."
#: ../interfaces.py:249
msgid "help_edit_comment_enabled"
msgstr ""
#. Default: "If selected, users are able to post comments on the site. Though, you have to enable comments for specific content types, folders or content objects before users will be able to post comments."
#: ../interfaces.py:26
#: ../interfaces.py:202
msgid "help_globally_enabled"
msgstr "Je-li zaškrtnuto, uživatelé mohou přidávat komentáře. Navíc však musíte ověřit, že je povoleno přidávání komentářů k příslušným typům položek."
#. Default: "If selected, comments will enter a 'Pending' state in which they are invisible to the public. A user with the 'Review comments' permission ('Reviewer' or 'Manager') can approve comments to make them visible to the public. If you want to enable a custom comment workflow, you have to go to the types control panel."
#: ../interfaces.py:50
#: ../interfaces.py:232
msgid "help_moderation_enabled"
msgstr "Je-li zaškrtnuto, pakbudou komentáře moderované. Po zadání komentáře bude tento komentář ve stavu \"čeká na schválení\" a nebude viditelný nepřihlášeným návštěvníkům. Moderátor (uživatel, ktewrý má opravnění schvalovat komentáře) může takové komentáře schválit a tedy zviditelnit všem."
#. Default: "Address to which moderator notifications will be sent."
#: ../interfaces.py:118
#: ../interfaces.py:329
msgid "help_moderator_email"
msgstr "Adresa, na kterou budou zasílány notifikační emaily moderátorlů"
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be found in the 'Mail settings' control panel (Site 'From' address)"
#: ../interfaces.py:107
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be set below."
#: ../interfaces.py:315
#, fuzzy
msgid "help_moderator_notification_enabled"
msgstr "Je-li zaškrtnuto, moderátor je upozorněn na komentáře, které vyžadují jeho zásah."
#. Default: "If selected, an image of the user is shown next to the comment."
#: ../interfaces.py:97
#: ../interfaces.py:304
msgid "help_show_commenter_image"
msgstr "Je-li zaškrtnuto, je vedle komentáře zobrazen portrét autora komentáře."
#. Default: "Use this setting to choose if the comment text should be transformed in any way. You can choose between 'Plain text' and 'Intelligent text'. 'Intelligent text' converts plain text into HTML where line breaks and indentation is preserved, and web and email addresses are made into clickable links."
#: ../interfaces.py:66
#: ../interfaces.py:271
msgid "help_text_transform"
msgstr "Zde můžete nastavit, zda mají být komentáře nějak upraveny. Je možné vybrat mezi Plain text (prostý, neupravený text) nebo \"Intelligent text\". Intelligent text konvertuje odkazy na aktivní linky a převádí text do HTML tak, jak je vidět na obrazovce (tedy se zachováním nových řádků a odsazení)."
#. Default: "If selected, users can choose to be notified of new comments by email."
#: ../interfaces.py:127
#: ../interfaces.py:341
msgid "help_user_notification_enabled"
msgstr "Je-li zaškrtnuto, uživatelé se mohou rozhodnout zda si přejí být upozorněni na nové komentáře emailem."
#. Default: "Anonymous"
#: ../comment.py:156
#: ../browser/comments.pt:75
#: ../comment.py:193
msgid "label_anonymous"
msgstr "Anonym"
#. Default: "Enable anonymous comments"
#: ../interfaces.py:36
#: ../interfaces.py:214
msgid "label_anonymous_comments"
msgstr "Povolit anonymní komentáře"
#. Default: "Enable anonymous email field"
#: ../interfaces.py:350
msgid "label_anonymous_email_enabled"
msgstr ""
#. Default: "Apply"
#: ../browser/moderation.pt:71
msgid "label_apply"
msgstr "Provést"
#. Default: "Captcha"
#: ../interfaces.py:80
#: ../interfaces.py:286
msgid "label_captcha"
msgstr "Captcha"
#. Default: "Comment"
#: ../interfaces.py:275
#: ../interfaces.py:163
msgid "label_comment"
msgstr "Komentář"
#. Default: "Commenting has been disabled."
#: ../browser/comments.pt:130
#: ../browser/comments.pt:163
msgid "label_commenting_disabled"
msgstr "Komentáře byly zakázány."
@ -295,23 +384,33 @@ msgstr "Komentáře byly zakázány."
msgid "label_delete"
msgstr "Odebrat"
#. Default: "Enable deleting own comments"
#: ../interfaces.py:258
msgid "label_delete_own_comment_enabled"
msgstr ""
#. Default: "Enable editing of comments"
#: ../interfaces.py:247
msgid "label_edit_comment_enabled"
msgstr ""
#. Default: "Globally enable comments"
#: ../interfaces.py:24
#: ../interfaces.py:200
msgid "label_globally_enabled"
msgstr "Globální povolení komentářů"
#. Default: "Enable comment moderation"
#: ../interfaces.py:48
#: ../interfaces.py:228
msgid "label_moderation_enabled"
msgstr "Povolit moderování komentářů"
#. Default: "Moderator Email Address"
#: ../interfaces.py:117
#: ../interfaces.py:325
msgid "label_moderator_email"
msgstr "Email adresa moderátora"
#. Default: "Enable moderator email notification"
#: ../interfaces.py:105
#: ../interfaces.py:313
msgid "label_moderator_notification_enabled"
msgstr "Povolit emailovou notifikaci moderátorů"
@ -321,12 +420,12 @@ msgid "label_publish"
msgstr "Schválit"
#. Default: "says:"
#: ../browser/comments.pt:74
#: ../browser/comments.pt:78
msgid "label_says"
msgstr "píše:"
#. Default: "Show commenter image"
#: ../interfaces.py:95
#: ../interfaces.py:302
msgid "label_show_commenter_image"
msgstr "Zobrazit portrét komentujícího"
@ -336,29 +435,45 @@ msgid "label_show_full_comment_text"
msgstr "zobrazit celý text příspěvku"
#. Default: "Subject"
#: ../interfaces.py:271
#: ../interfaces.py:158
msgid "label_subject"
msgstr "Předmět"
#. Default: "Comment text transform"
#: ../interfaces.py:64
#: ../interfaces.py:269
msgid "label_text_transform"
msgstr "Transformace textu"
#. Default: "Enable user email notification"
#: ../interfaces.py:125
#: ../interfaces.py:337
msgid "label_user_notification_enabled"
msgstr "Povolit notifikaci uživatelů emailem"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n"
#: ../comment.py:50
#: ../comment.py:61
msgid "mail_notification_message"
msgstr "Na adrese ${link} byl přidán komentář k položce '${title}'}\n\n---\n${text}\n---"
msgstr ""
"Na adrese ${link} byl přidán komentář k položce '${title}'}\n"
"\n"
"---\n"
"${text}\n"
"---"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n\nApprove comment:\n${link_approve}\n\nDelete comment:\n${link_delete}\n"
#: ../comment.py:58
#: ../comment.py:69
msgid "mail_notification_message_moderator"
msgstr "Na adrese ${link} byl vložen komentář k položce '${title}'\n\n---\n${text}\n---\n\nSchválit komentář:\n${link_approve}\n\nSmazat komentář:\n${link_delete}"
msgstr ""
"Na adrese ${link} byl vložen komentář k položce '${title}'\n"
"\n"
"---\n"
"${text}\n"
"---\n"
"\n"
"Schválit komentář:\n"
"${link_approve}\n"
"\n"
"Smazat komentář:\n"
"${link_delete}"
#. Default: "enable the 'Comment Review Workflow' for the Comment content type"
#: ../browser/moderation.pt:33

View File

@ -14,136 +14,172 @@ msgstr ""
"Preferred-Encodings: utf-8\n"
"Domain: plone.app.discussion\n"
#: ../comment.py:264
#: ../comment.py:359
msgid "A comment has been posted."
msgstr "En kommentar er gem."
msgstr "Der er oprettet en kommentar."
#: ../interfaces.py:257
#: ../interfaces.py:144
msgid "A comment id unique to this conversation"
msgstr "En kommentar-id som er unik for denne dialog"
msgstr "Et kommentar-id som er unikt for denne dialog"
#: ../browser/comments.py:67
#: ../browser/comments.py:72
msgid "Add a comment"
msgstr "Tilføj en kommentar"
#: ../browser/controlpanel.py:62
#: ../browser/controlpanel.py:75
msgid "Anonymous Comments"
msgstr "Anonyme kommentarer"
#: ../interfaces.py:282
msgid "Author name (for display)"
msgstr "Forfatter"
#: ../browser/comments.py:248
#: ../browser/controlpanel.py:80
#: ../browser/comments.py:275
#: ../browser/controlpanel.py:93
msgid "Cancel"
msgstr "Afbryd"
#: ../browser/controlpanel.py:76
#: ../interfaces.py:184
msgid "Captcha"
msgstr ""
#: ../browser/controlpanel.py:89
msgid "Changes saved"
msgstr "Ændringer gemt"
#: ../browser/moderation.py:133
#: ../browser/moderation.py:186
msgid "Comment approved."
msgstr "Kommentar godkendt."
#: ../browser/moderation.py:94
#: ../contentrules.py:92
msgid "Comment author email"
msgstr ""
#: ../contentrules.py:81
msgid "Comment author full name"
msgstr ""
#: ../contentrules.py:70
msgid "Comment author user name"
msgstr ""
#: ../browser/moderation.py:111
msgid "Comment deleted."
msgstr "Kommentar slettet."
#: ../browser/controlpanel.py:63
#: ../contentrules.py:48
msgid "Comment id"
msgstr ""
#: ../contentrules.py:59
msgid "Comment text"
msgstr ""
#: ../browser/controlpanel.py:76
msgid "Commenter Image"
msgstr "Kommentar-billede"
msgid "Commenting infrastructure for Plone"
msgstr "Kommentar-funktionalitet til Plone"
#: ../interfaces.py:252
#: ../contentrules.py:47
msgid "Comments"
msgstr ""
#: ../interfaces.py:139
msgid "Conversation"
msgstr "Dialog"
#: ../interfaces.py:283
#: ../interfaces.py:177
msgid "Creation date"
msgstr "Oprettelses-dato"
#: ../interfaces.py:162
msgid "Date of the most recent comment"
msgstr "Dato for den seneste kommentar"
#: ../interfaces.py:41
msgid "Date of the most recent public comment"
msgstr "Dato for den seneste, offentlige kommentar"
#: ../vocabularies.py:44
msgid "Disabled"
msgstr "Slået fra"
#: ../browser/controlpanel.py:32
#: ../browser/controlpanel.py:33
msgid "Discussion settings"
msgstr "Indstilling for kommentarer"
#: ../browser/controlpanel.py:82
#: ../browser/controlpanel.py:95
msgid "Edit cancelled"
msgstr "Redigering blev afbrudt"
#: ../interfaces.py:269
#: ../interfaces.py:156
msgid "Email"
msgstr "Email"
msgstr "E-mail"
#: ../browser/controlpanel.py:61
#: ../browser/controlpanel.py:74
msgid "Enable Comments"
msgstr "Slå kommentarer til"
#: ../interfaces.py:260
#: ../interfaces.py:147
msgid "Id of comment this comment is in reply to"
msgstr "Id'en på den kommentar, denne kommentar er et svar til"
msgstr "Id'et på den kommentar, denne kommentar er et svar til"
#: ../interfaces.py:274
#: ../interfaces.py:161
msgid "MIME type"
msgstr "MIME-type"
#: ../browser/controlpanel.py:65
#: ../browser/controlpanel.py:78
msgid "Moderator Email Notification"
msgstr "Notificering af moderator"
#: ../interfaces.py:284
#: ../interfaces.py:178
msgid "Modification date"
msgstr "Ændringsdato"
#: ../interfaces.py:254
#: ../interfaces.py:141
msgid "Name"
msgstr "Navn"
#: ../interfaces.py:278
#: ../interfaces.py:170
msgid "Notify me of new comments via email."
msgstr "Send besked om nye kommentarer pr. email."
msgstr "Send besked om nye kommentarer per e-mail."
#: ./plone.app.discussion/plone/app/discussion/configure.zcml
msgid "Plone Discussions"
msgstr "Plone diskussioner"
#: ../interfaces.py:247
#: ../interfaces.py:134
msgid "Portal type"
msgstr "Portal type"
msgstr "Portaltype"
#: ../browser/controlpanel.py:69
#: ../browser/controlpanel.py:82
msgid "Save"
msgstr "Gem"
#: ../interfaces.py:167
#: ../interfaces.py:46
msgid "The set of unique commentators (usernames)"
msgstr "Liste over kommentatorer (brugernavne)"
#: ../interfaces.py:156
msgid "Total number of comments on this item"
msgstr "Kommentarer i alt på denne side"
#: ../interfaces.py:51
msgid "The set of unique commentators (usernames) of published_comments"
msgstr "Gruppen af unikke kommentatorer (brugernavne) fra published_comments"
#: ../browser/controlpanel.py:67
#: ../interfaces.py:35
msgid "Total number of public comments on this item"
msgstr "Det samlede antal offentlige kommentarer til dette element"
#: ../comment.py:175
msgid "Transform '%s' => '%s' not available."
msgstr ""
#: ../browser/controlpanel.py:80
msgid "User Email Notification"
msgstr "Email-notificering af brugere"
msgstr "E-mail-notificering af brugere"
#: ../browser/comments.py:241
#: ../interfaces.py:176
msgid "Username of the commenter"
msgstr "Kommentatorens brugernavn"
#: ../browser/comments.py:268
msgid "Your comment awaits moderator approval."
msgstr "Din kommentar venter på godkendelse."
#. Default: "Comment"
#: ../browser/comments.py:123
#: ../browser/comments.py:138
msgid "add_comment_button"
msgstr "Gem"
@ -157,26 +193,57 @@ msgstr "Slet"
msgid "bulkactions_publish"
msgstr "Godkend"
#. Default: "Cancel"
#: ../browser/comment.py:97
msgid "cancel_form_button"
msgstr ""
#. Default: "You can add a comment by filling out the form below. Plain text formatting. Web and email addresses are transformed into clickable links."
#: ../browser/comments.py:52
#: ../browser/comments.py:57
msgid "comment_description_intelligent_text"
msgstr "Du kan tilføje en kommentar ved at udfylde formularen nedenfor. Ren tekst-formattering. Web- og emailadresser bliver automatisk lavet om til klikbare links."
msgstr "Du kan tilføje en kommentar ved at udfylde formularen nedenfor. Ren tekst-formattering. Web- og e-mailadresser bliver automatisk lavet om til klikbare links."
#. Default: "You can add a comment by filling out the form below. Plain text formatting. You can use the Markdown syntax for links and images."
#: ../browser/comments.py:51
msgid "comment_description_markdown"
msgstr ""
#. Default: "Comments are moderated."
#: ../browser/comments.py:58
#: ../browser/comments.py:63
msgid "comment_description_moderation_enabled"
msgstr "Kommentarer er modereret."
#. Default: "You can add a comment by filling out the form below. Plain text formatting."
#: ../browser/comments.py:47
#: ../browser/comments.py:46
msgid "comment_description_plain_text"
msgstr "Du kan tilføje en kommentar ved at udfylde formularen nedenfor. Ren tekst-formattering."
#. Default: "${creator} on ${content}"
#: ../comment.py:46
#. Default: "Edit comment cancelled"
#: ../browser/comment.py:101
msgid "comment_edit_cancel_notification"
msgstr ""
#. Default: "Comment was edited"
#: ../browser/comment.py:91
msgid "comment_edit_notification"
msgstr ""
#. Default: "${author_name} on ${content}"
#: ../comment.py:57
#, fuzzy
msgid "comment_title"
msgstr "${creator} på ${content}"
#. Default: "Edit comment"
#: ../browser/comment.py:70
msgid "edit_comment_form_button"
msgstr ""
#. Default: "Edit comment"
#: ../browser/comment.py:54
msgid "edit_comment_form_title"
msgstr ""
#. Default: "Action"
#: ../browser/moderation.pt:85
msgid "heading_action"
@ -208,82 +275,104 @@ msgid "heading_moderate_comments"
msgstr "Moderer kommentarer"
#. Default: "If selected, anonymous users are able to post comments without loggin in. It is highly recommended to use a captcha solution to prevent spam if this setting is enabled."
#: ../interfaces.py:38
#: ../interfaces.py:216
msgid "help_anonymous_comments"
msgstr "Hvis du krydser af, kan anonyme brugere skrive kommentarer uden at være logget ind. I så fald er det en god ide at bruge CAPTCHA for at forhindre spam."
#. Default: "If selected, anonymous user will have to give their email."
#: ../interfaces.py:352
msgid "help_anonymous_email_enabled"
msgstr ""
#. Default: "Use this setting to enable or disable Captcha validation for comments. Install plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet, or collective.z3cform.norobots if there are no options available."
#: ../interfaces.py:82
#: ../interfaces.py:288
msgid "help_captcha"
msgstr "Her kan du slå CAPTCHA til og fra for kommentarer. Installer plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet eller collective.z3cform.norobots, hvis der ikke er nogen valgmuligheder nedenfor."
#. Default: "If selected, supports deleting of own comments for users with the 'Delete own comments' permission."
#: ../interfaces.py:260
msgid "help_delete_own_comment_enabled"
msgstr ""
#. Default: "Some discussion related settings are not located in the Discussion Control Panel.\nTo enable comments for a specific content type, go to the Types Control Panel of this type and choose \"Allow comments\".\nTo enable the moderation workflow for comments, go to the Types Control Panel, choose \"Comment\" and set workflow to \"Comment Review Workflow\"."
#: ../browser/controlpanel.py:33
#: ../browser/controlpanel.py:34
msgid "help_discussion_settings_editform"
msgstr "Du kan justere kommentarindstillingerne nedenfor. Bemærk, at der også er indstillinger andre steder, som påvirker kommentarer. For at slå kommentarer til for en bestemt indholdstype, så klik \"Typer\" på Kontrolpanelet og afkryds \"Tillad kommentarer\" for typen. For at slå modereringsworkflow til kommentarer, så vælg \"Kommentar\" under \"Typer\" på Kontrolpanelet og vælg workflowet \"Godkendelses-workflow for kommentarer\""
#. Default: "If selected, supports editing of comments for users with the 'Edit comments' permission."
#: ../interfaces.py:249
msgid "help_edit_comment_enabled"
msgstr ""
#. Default: "If selected, users are able to post comments on the site. Though, you have to enable comments for specific content types, folders or content objects before users will be able to post comments."
#: ../interfaces.py:26
#: ../interfaces.py:202
msgid "help_globally_enabled"
msgstr "Hvis du krydser af, kan brugere skrive kommentarer på sitet. Du skal dog først slå kommentering til for bestemte indholdstyper, mapper eller indholdsobjekter, før det virker."
#. Default: "If selected, comments will enter a 'Pending' state in which they are invisible to the public. A user with the 'Review comments' permission ('Reviewer' or 'Manager') can approve comments to make them visible to the public. If you want to enable a custom comment workflow, you have to go to the types control panel."
#: ../interfaces.py:50
#: ../interfaces.py:232
msgid "help_moderation_enabled"
msgstr "Hvis du krydser af, vil kommentarer automatisk bliver sat i en \"Afventer\"-tilstand, hvor de er usynlige for offentligheden. En bruger med rettigheder til at moderere kommentarer kan godkende kommentarer og gøre dem synlige for offentligheden."
#. Default: "Address to which moderator notifications will be sent."
#: ../interfaces.py:118
#: ../interfaces.py:329
msgid "help_moderator_email"
msgstr "Adresse på den person, som skal modtage moderator-notificeringer."
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be found in the 'Mail settings' control panel (Site 'From' address)"
#: ../interfaces.py:107
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be set below."
#: ../interfaces.py:315
#, fuzzy
msgid "help_moderator_notification_enabled"
msgstr "Hvis du krydser af, får en moderator besked, hvis en kommentarer skal vurderes."
#. Default: "If selected, an image of the user is shown next to the comment."
#: ../interfaces.py:97
#: ../interfaces.py:304
msgid "help_show_commenter_image"
msgstr "Hvis du krydser af, bliver der vist et billede af brugeren ved siden af kommentaren."
#. Default: "Use this setting to choose if the comment text should be transformed in any way. You can choose between 'Plain text' and 'Intelligent text'. 'Intelligent text' converts plain text into HTML where line breaks and indentation is preserved, and web and email addresses are made into clickable links."
#: ../interfaces.py:66
#: ../interfaces.py:271
msgid "help_text_transform"
msgstr "Vælg, hvordan kommentartekster skal vises. Du kan vælge mellem \"Plan text\", \"Markdown\" og \"Intelligent text\". Plain text gør ingenting. Markdown fortolker teksten efter Markdown-standarden. Intelligent text oversætter teksten til HTML og bibeholder indrykninger, linjeskift og oversætter emails og webadresser til klikbare links."
#. Default: "If selected, users can choose to be notified of new comments by email."
#: ../interfaces.py:127
#: ../interfaces.py:341
msgid "help_user_notification_enabled"
msgstr "Hvis den er slået til, kan brugere få besked om nye kommentarer over email."
#. Default: "Anonymous"
#: ../comment.py:156
#: ../browser/comments.pt:75
#: ../comment.py:193
msgid "label_anonymous"
msgstr "Anonym"
#. Default: "Enable anonymous comments"
#: ../interfaces.py:36
#: ../interfaces.py:214
msgid "label_anonymous_comments"
msgstr "Slå anonym kommentering til"
#. Default: "Enable anonymous email field"
#: ../interfaces.py:350
msgid "label_anonymous_email_enabled"
msgstr ""
#. Default: "Apply"
#: ../browser/moderation.pt:71
msgid "label_apply"
msgstr "Udfør"
#. Default: "Captcha"
#: ../interfaces.py:80
#: ../interfaces.py:286
msgid "label_captcha"
msgstr "CAPTCHA"
#. Default: "Comment"
#: ../interfaces.py:275
#: ../interfaces.py:163
msgid "label_comment"
msgstr "Kommentar"
#. Default: "Commenting has been disabled."
#: ../browser/comments.pt:130
#: ../browser/comments.pt:163
msgid "label_commenting_disabled"
msgstr "Kommentering er slået fra."
@ -292,23 +381,33 @@ msgstr "Kommentering er slået fra."
msgid "label_delete"
msgstr "Slet"
#. Default: "Enable deleting own comments"
#: ../interfaces.py:258
msgid "label_delete_own_comment_enabled"
msgstr ""
#. Default: "Enable editing of comments"
#: ../interfaces.py:247
msgid "label_edit_comment_enabled"
msgstr ""
#. Default: "Globally enable comments"
#: ../interfaces.py:24
#: ../interfaces.py:200
msgid "label_globally_enabled"
msgstr "Tænd for kommentarer"
#. Default: "Enable comment moderation"
#: ../interfaces.py:48
#: ../interfaces.py:228
msgid "label_moderation_enabled"
msgstr "Slå kommentarmoderering til"
#. Default: "Moderator Email Address"
#: ../interfaces.py:117
#: ../interfaces.py:325
msgid "label_moderator_email"
msgstr "Email på moderator"
#. Default: "Enable moderator email notification"
#: ../interfaces.py:105
#: ../interfaces.py:313
msgid "label_moderator_notification_enabled"
msgstr "Slå moderatorer-notificering til"
@ -318,12 +417,12 @@ msgid "label_publish"
msgstr "Godkend"
#. Default: "says:"
#: ../browser/comments.pt:74
#: ../browser/comments.pt:78
msgid "label_says"
msgstr "siger:"
#. Default: "Show commenter image"
#: ../interfaces.py:95
#: ../interfaces.py:302
msgid "label_show_commenter_image"
msgstr "Vis kommentator-billede"
@ -333,30 +432,41 @@ msgid "label_show_full_comment_text"
msgstr "Hvis fuld kommentar"
#. Default: "Subject"
#: ../interfaces.py:271
#: ../interfaces.py:158
msgid "label_subject"
msgstr "Emne"
#. Default: "Comment text transform"
#: ../interfaces.py:64
#: ../interfaces.py:269
msgid "label_text_transform"
msgstr "Formattering af kommentar-tekst"
#. Default: "Enable user email notification"
#: ../interfaces.py:125
#: ../interfaces.py:337
msgid "label_user_notification_enabled"
msgstr "Slå bruger-notificering til"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n"
#: ../comment.py:50
#: ../comment.py:61
#, fuzzy
msgid "mail_notification_message"
msgstr "En kommentarer om '${title}' er blevet gemt her: ${link}"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n\nApprove comment:\n${link_approve}\n\nDelete comment:\n${link_delete}\n"
#: ../comment.py:58
#: ../comment.py:69
msgid "mail_notification_message_moderator"
msgstr "En kommentar til '${title}' er blevet indsendt her: ${link}\n\n---\n${text}\n---\n\nGodkend kommentar:\n${link_approve}\n\nSlet kommentar:\n${link_delete}\n"
msgstr ""
"En kommentar til '${title}' er blevet indsendt her: ${link}\n"
"\n"
"---\n"
"${text}\n"
"---\n"
"\n"
"Godkend kommentar:\n"
"${link_approve}\n"
"\n"
"Slet kommentar:\n"
"${link_delete}\n"
#. Default: "enable the 'Comment Review Workflow' for the Comment content type"
#: ../browser/moderation.pt:33

View File

@ -1 +0,0 @@
/plone.app.discussion.mo

View File

@ -14,133 +14,172 @@ msgstr ""
"Preferred-Encodings: utf-8 latin1\n"
"Domain: plone.app.discussion\n"
#: ../comment.py:264
#: ../comment.py:359
msgid "A comment has been posted."
msgstr "Ein Kommentar wurde abgegeben."
#: ../interfaces.py:257
#: ../interfaces.py:144
msgid "A comment id unique to this conversation"
msgstr "Eine eindeutige ID des Kommentars"
#: ../browser/comments.py:67
#: ../browser/comments.py:72
msgid "Add a comment"
msgstr "Kommentar hinzufügen"
#: ../browser/controlpanel.py:62
#: ../browser/controlpanel.py:75
msgid "Anonymous Comments"
msgstr "Anonyme Kommentare"
#: ../interfaces.py:282
msgid "Author name (for display)"
msgstr "Name des Autors (wird angezeigt)"
#: ../browser/comments.py:248
#: ../browser/controlpanel.py:80
#: ../browser/comments.py:275
#: ../browser/controlpanel.py:93
msgid "Cancel"
msgstr "Abbrechen"
#: ../browser/controlpanel.py:76
#: ../interfaces.py:184
msgid "Captcha"
msgstr ""
#: ../browser/controlpanel.py:89
msgid "Changes saved"
msgstr "Änderungen gespeichert"
#: ../browser/moderation.py:133
#: ../browser/moderation.py:186
msgid "Comment approved."
msgstr "Kommentar zur Veröffentlichung freigegeben."
#: ../browser/moderation.py:94
#: ../contentrules.py:92
msgid "Comment author email"
msgstr ""
#: ../contentrules.py:81
msgid "Comment author full name"
msgstr ""
#: ../contentrules.py:70
msgid "Comment author user name"
msgstr ""
#: ../browser/moderation.py:111
msgid "Comment deleted."
msgstr "Kommentar gelöscht"
#: ../browser/controlpanel.py:63
#: ../contentrules.py:48
msgid "Comment id"
msgstr ""
#: ../contentrules.py:59
msgid "Comment text"
msgstr ""
#: ../browser/controlpanel.py:76
msgid "Commenter Image"
msgstr "Porträt des Benutzers"
#: ../interfaces.py:252
msgid "Commenting infrastructure for Plone"
msgstr ""
#: ../contentrules.py:47
msgid "Comments"
msgstr ""
#: ../interfaces.py:139
msgid "Conversation"
msgstr "Diskussion"
#: ../interfaces.py:283
#: ../interfaces.py:177
msgid "Creation date"
msgstr "Erstellungsdatum"
#: ../interfaces.py:162
msgid "Date of the most recent comment"
msgstr "Datum des letzten Kommentars"
#: ../interfaces.py:41
msgid "Date of the most recent public comment"
msgstr "Datum des neuesten öffentlichen Kommentars"
#: ../vocabularies.py:44
msgid "Disabled"
msgstr "Ausgeschaltet"
#: ../browser/controlpanel.py:32
#: ../browser/controlpanel.py:33
msgid "Discussion settings"
msgstr "Kommentierungseinstellungen"
#: ../browser/controlpanel.py:82
#: ../browser/controlpanel.py:95
msgid "Edit cancelled"
msgstr ""
msgstr "Bearbeitung abgebrochen"
#: ../interfaces.py:269
#: ../interfaces.py:156
msgid "Email"
msgstr "E-Mail"
#: ../browser/controlpanel.py:61
#: ../browser/controlpanel.py:74
msgid "Enable Comments"
msgstr "Kommentare einschalten"
#: ../interfaces.py:260
#: ../interfaces.py:147
msgid "Id of comment this comment is in reply to"
msgstr "ID des Kommentars, auf den geantwortet wird."
#: ../interfaces.py:274
#: ../interfaces.py:161
msgid "MIME type"
msgstr "MIME-Typ"
#: ../browser/controlpanel.py:65
#: ../browser/controlpanel.py:78
msgid "Moderator Email Notification"
msgstr "Moderator E-Mail Benachrichtigung"
#: ../interfaces.py:284
#: ../interfaces.py:178
msgid "Modification date"
msgstr "Änderungsdatum"
#: ../interfaces.py:254
#: ../interfaces.py:141
msgid "Name"
msgstr "Name"
#: ../interfaces.py:278
#: ../interfaces.py:170
msgid "Notify me of new comments via email."
msgstr "E-Mail-Benachrichtigung bei neuen Kommentaren"
#: ./plone.app.discussion/plone/app/discussion/configure.zcml
msgid "Plone Discussions"
msgstr "Plone Diskussionen"
msgstr ""
#: ../interfaces.py:247
#: ../interfaces.py:134
msgid "Portal type"
msgstr "Artikeltyp"
#: ../browser/controlpanel.py:69
#: ../browser/controlpanel.py:82
msgid "Save"
msgstr "Speichern"
#: ../interfaces.py:167
#: ../interfaces.py:46
msgid "The set of unique commentators (usernames)"
msgstr "Liste von Benutzern, die Kommentare abgegeben haben"
#: ../interfaces.py:156
msgid "Total number of comments on this item"
msgstr "Anzahl der Kommentare zu diesem Artikel"
#: ../interfaces.py:51
msgid "The set of unique commentators (usernames) of published_comments"
msgstr ""
#: ../browser/controlpanel.py:67
#: ../interfaces.py:35
msgid "Total number of public comments on this item"
msgstr "Summe der veröffentlichten Kommentare zu diesem Artikel"
#: ../comment.py:175
msgid "Transform '%s' => '%s' not available."
msgstr "Transformation '%s' => '%s' ist nicht verfügbar."
#: ../browser/controlpanel.py:80
msgid "User Email Notification"
msgstr "E-Mail-Benachrichtigungen für Benutzer"
#: ../browser/comments.py:241
#: ../interfaces.py:176
msgid "Username of the commenter"
msgstr "Benutzername des Kommentierenden"
#: ../browser/comments.py:268
msgid "Your comment awaits moderator approval."
msgstr "Ihr Kommentar muss noch vom Moderator freigegeben werden."
#. Default: "Comment"
#: ../browser/comments.py:123
#: ../browser/comments.py:138
msgid "add_comment_button"
msgstr "Kommentieren"
@ -154,24 +193,54 @@ msgstr "Löschen"
msgid "bulkactions_publish"
msgstr "Veröffentlichen"
#. Default: "Cancel"
#: ../browser/comment.py:97
msgid "cancel_form_button"
msgstr ""
#. Default: "You can add a comment by filling out the form below. Plain text formatting. Web and email addresses are transformed into clickable links."
#: ../browser/comments.py:52
#: ../browser/comments.py:57
msgid "comment_description_intelligent_text"
msgstr "Sie können einen Kommentar abgeben, indem Sie das untenstehende Formular ausfüllen. Nur Text. Web- und E-Mailadressen werden in anklickbare Links umgewandelt."
#. Default: "You can add a comment by filling out the form below. Plain text formatting. You can use the Markdown syntax for links and images."
#: ../browser/comments.py:51
msgid "comment_description_markdown"
msgstr "Sie können einen Kommentar abgeben, indem Sie das untenstehende Formular ausfüllen. Sie können die Markdown-Syntax für Links und Bilder benutzen."
#. Default: "Comments are moderated."
#: ../browser/comments.py:58
#: ../browser/comments.py:63
msgid "comment_description_moderation_enabled"
msgstr "Kommentare werden moderiert."
#. Default: "You can add a comment by filling out the form below. Plain text formatting."
#: ../browser/comments.py:47
#: ../browser/comments.py:46
msgid "comment_description_plain_text"
msgstr "Sie können einen Kommentar abgeben, indem Sie das untenstehende Formular ausfüllen. Nur Text."
#. Default: "${creator} on ${content}"
#: ../comment.py:46
#. Default: "Edit comment cancelled"
#: ../browser/comment.py:101
msgid "comment_edit_cancel_notification"
msgstr ""
#. Default: "Comment was edited"
#: ../browser/comment.py:91
msgid "comment_edit_notification"
msgstr ""
#. Default: "${author_name} on ${content}"
#: ../comment.py:57
msgid "comment_title"
msgstr "${author_name} zu ${content}"
#. Default: "Edit comment"
#: ../browser/comment.py:70
msgid "edit_comment_form_button"
msgstr ""
#. Default: "Edit comment"
#: ../browser/comment.py:54
msgid "edit_comment_form_title"
msgstr ""
#. Default: "Action"
@ -205,18 +274,28 @@ msgid "heading_moderate_comments"
msgstr "Kommentare moderieren"
#. Default: "If selected, anonymous users are able to post comments without loggin in. It is highly recommended to use a captcha solution to prevent spam if this setting is enabled."
#: ../interfaces.py:38
#: ../interfaces.py:216
msgid "help_anonymous_comments"
msgstr "Wenn Sie diese Einstellung aktivieren, können anonyme Benutzer Kommentare abgeben. Es ist empfehlenswert, dann auch Captchas zu aktivieren."
#. Default: "If selected, anonymous user will have to give their email."
#: ../interfaces.py:352
msgid "help_anonymous_email_enabled"
msgstr "Wenn Sie diese Einstellung aktivieren, müssen anonyme Benutzer ihre E-Mail-Adresse angeben."
#. Default: "Use this setting to enable or disable Captcha validation for comments. Install plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet, or collective.z3cform.norobots if there are no options available."
#: ../interfaces.py:82
#: ../interfaces.py:288
#, fuzzy
msgid "help_captcha"
msgstr "Wenn Sie diese Einstellung aktivieren, wird mit Hilfe der Captcha-Validierung überprüft, ob die Kommentare von einem echten Benutzer oder von einem automatisierten Skript stammen. Falls Sie die Option nicht einschalten können, fehlt evtl. ein benötigtes Programmmodul. Stellen Sie sicher, dass entweder plone.formwidget.captcha oder plone.formwidget.recaptcha installiert ist."
#. Default: "If selected, supports deleting of own comments for users with the 'Delete own comments' permission."
#: ../interfaces.py:260
msgid "help_delete_own_comment_enabled"
msgstr ""
#. Default: "Some discussion related settings are not located in the Discussion Control Panel.\nTo enable comments for a specific content type, go to the Types Control Panel of this type and choose \"Allow comments\".\nTo enable the moderation workflow for comments, go to the Types Control Panel, choose \"Comment\" and set workflow to \"Comment Review Workflow\"."
#: ../browser/controlpanel.py:33
#: ../browser/controlpanel.py:34
#, fuzzy
msgid "help_discussion_settings_editform"
msgstr ""
@ -224,94 +303,116 @@ msgstr ""
"\n"
"Um die Moderation von Kommentaren zu aktivieren, wählen Sie den Artikeltyp 'Kommentar' aus und wählen Sie als neuen Arbeitsablauf 'Arbeitsablauf für moderierte Kommentare'."
#. Default: "If selected, supports editing of comments for users with the 'Edit comments' permission."
#: ../interfaces.py:249
msgid "help_edit_comment_enabled"
msgstr ""
#. Default: "If selected, users are able to post comments on the site. Though, you have to enable comments for specific content types, folders or content objects before users will be able to post comments."
#: ../interfaces.py:26
#: ../interfaces.py:202
#, fuzzy
msgid "help_globally_enabled"
msgstr "Wenn Sie diese Einstellung aktivieren, können Artikel generell kommentiert werden."
#. Default: "If selected, comments will enter a 'Pending' state in which they are invisible to the public. A user with the 'Review comments' permission ('Reviewer' or 'Manager') can approve comments to make them visible to the public. If you want to enable a custom comment workflow, you have to go to the types control panel."
#: ../interfaces.py:50
#: ../interfaces.py:232
msgid "help_moderation_enabled"
msgstr ""
msgstr "Falls ausgewählt werden Kommentare in einem für die Öffentlichkeit unsichtbaren Schwebezustand gehalten, bis sie ein Benutzer mit der 'Review comments' Berechtigung ('Reviewer' or 'Manager') genehmigt und damit für die Öffentlichkeit sichtbar macht. Wenn Sie einen angepassten Arbeitsablauf für Kommentare einstellen wollen, so geht das mit dem Menu unter Artikeltypen."
#. Default: "Address to which moderator notifications will be sent."
#: ../interfaces.py:118
#: ../interfaces.py:329
msgid "help_moderator_email"
msgstr "E-Mail Adresse an welche die Moderatoren-Benachrichtigungen gesendet werden."
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be found in the 'Mail settings' control panel (Site 'From' address)"
#: ../interfaces.py:107
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be set below."
#: ../interfaces.py:315
#, fuzzy
msgid "help_moderator_notification_enabled"
msgstr ""
msgstr "Falls ausgewählt erhält der Moderator eine E-Mail, wenn ein Kommentar Aufmerksamkeit braucht. Die E-Mail-Adresse des Moderators kann weiter unten angegeben werden."
#. Default: "If selected, an image of the user is shown next to the comment."
#: ../interfaces.py:97
#: ../interfaces.py:304
msgid "help_show_commenter_image"
msgstr "Wenn Sie diese Einstellung aktivieren, wird das Porträt des kommentierenden Benutzers neben dem Kommentar angezeigt."
#. Default: "Use this setting to choose if the comment text should be transformed in any way. You can choose between 'Plain text' and 'Intelligent text'. 'Intelligent text' converts plain text into HTML where line breaks and indentation is preserved, and web and email addresses are made into clickable links."
#: ../interfaces.py:66
#: ../interfaces.py:271
msgid "help_text_transform"
msgstr ""
msgstr "Diese Einstellung wählen, wenn eine Transformation in irgend einer Art und Weise gewünscht ist. Sie können zwischen 'Plain text' und 'Intelligent text' wählen. 'Intelligent text' wandelt Plain Text in HTML um, dabei werden Zeilenumbrüche und Einrückungen beibehalten sowie Weblinks und E-Mail-Adressen in klickbare Links verwandelt."
#. Default: "If selected, users can choose to be notified of new comments by email."
#: ../interfaces.py:127
#: ../interfaces.py:341
msgid "help_user_notification_enabled"
msgstr ""
msgstr "Wenn Sie diese Einstellung auswählen, können Benutzer angeben, dass sie über neue Kommentare per E-Mail informiert werden möchten."
#. Default: "Anonymous"
#: ../comment.py:156
#: ../browser/comments.pt:75
#: ../comment.py:193
msgid "label_anonymous"
msgstr "Anonymer Benutzer"
#. Default: "Enable anonymous comments"
#: ../interfaces.py:36
#: ../interfaces.py:214
msgid "label_anonymous_comments"
msgstr "Anonyme Kommentare"
#. Default: "Enable anonymous email field"
#: ../interfaces.py:350
msgid "label_anonymous_email_enabled"
msgstr "E-Mail Feld für anonyme Kommentare einschalten"
#. Default: "Apply"
#: ../browser/moderation.pt:71
msgid "label_apply"
msgstr "Anwenden"
#. Default: "Captcha"
#: ../interfaces.py:80
#: ../interfaces.py:286
msgid "label_captcha"
msgstr "Captcha"
#. Default: "Comment"
#: ../interfaces.py:275
#: ../interfaces.py:163
msgid "label_comment"
msgstr "Kommentar"
#. Default: "Commenting has been disabled."
#: ../browser/comments.pt:130
#: ../browser/comments.pt:163
msgid "label_commenting_disabled"
msgstr ""
msgstr "Kommentare wurden abgeschaltet."
#. Default: "Delete"
#: ../browser/moderation.pt:130
msgid "label_delete"
msgstr "Löschen"
#. Default: "Enable deleting own comments"
#: ../interfaces.py:258
msgid "label_delete_own_comment_enabled"
msgstr ""
#. Default: "Enable editing of comments"
#: ../interfaces.py:247
msgid "label_edit_comment_enabled"
msgstr ""
#. Default: "Globally enable comments"
#: ../interfaces.py:24
#: ../interfaces.py:200
msgid "label_globally_enabled"
msgstr "Kommentierungsfunktion generell einschalten"
#. Default: "Enable comment moderation"
#: ../interfaces.py:48
#: ../interfaces.py:228
msgid "label_moderation_enabled"
msgstr ""
msgstr "Moderation für Kommentare einschalten"
#. Default: "Moderator Email Address"
#: ../interfaces.py:117
#: ../interfaces.py:325
msgid "label_moderator_email"
msgstr ""
msgstr "E-Mail Adresse des Moderators"
#. Default: "Enable moderator email notification"
#: ../interfaces.py:105
#: ../interfaces.py:313
msgid "label_moderator_notification_enabled"
msgstr "Email-Benachrichtigungen für Moderatoren aktivieren"
@ -321,12 +422,12 @@ msgid "label_publish"
msgstr "Veröffentlichen"
#. Default: "says:"
#: ../browser/comments.pt:74
#: ../browser/comments.pt:78
msgid "label_says"
msgstr "sagt"
#. Default: "Show commenter image"
#: ../interfaces.py:95
#: ../interfaces.py:302
msgid "label_show_commenter_image"
msgstr "Zeige das Portrait des Kommentators"
@ -336,29 +437,45 @@ msgid "label_show_full_comment_text"
msgstr "Den vollständigen Kommentar anzeigen"
#. Default: "Subject"
#: ../interfaces.py:271
#: ../interfaces.py:158
msgid "label_subject"
msgstr "Betreff"
#. Default: "Comment text transform"
#: ../interfaces.py:64
#: ../interfaces.py:269
msgid "label_text_transform"
msgstr "Text transformationen"
#. Default: "Enable user email notification"
#: ../interfaces.py:125
#: ../interfaces.py:337
msgid "label_user_notification_enabled"
msgstr "E-Mail-Benachrichtigungen für Benutzer aktivieren"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n"
#: ../comment.py:50
#: ../comment.py:61
msgid "mail_notification_message"
msgstr "Ein Kommentar zu '${title}' wurde hier abgegeben: ${link}\n\n---\n${text}\n---\n"
msgstr ""
"Ein Kommentar zu '${title}' wurde hier abgegeben: ${link}\n"
"\n"
"---\n"
"${text}\n"
"---\n"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n\nApprove comment:\n${link_approve}\n\nDelete comment:\n${link_delete}\n"
#: ../comment.py:58
#: ../comment.py:69
msgid "mail_notification_message_moderator"
msgstr "Ein Kommentar zu '${title}' wurde hier abgegeben: ${link}\n\n---\n${text}\n---\n\nKommentar zur Veröffentlichung freigeben:\n${link_approve}\n\nKommentar löschen:\n${link_delete}\n"
msgstr ""
"Ein Kommentar zu '${title}' wurde hier abgegeben: ${link}\n"
"\n"
"---\n"
"${text}\n"
"---\n"
"\n"
"Kommentar zur Veröffentlichung freigeben:\n"
"${link_approve}\n"
"\n"
"Kommentar löschen:\n"
"${link_delete}\n"
#. Default: "enable the 'Comment Review Workflow' for the Comment content type"
#: ../browser/moderation.pt:33

View File

@ -3,9 +3,9 @@ msgid ""
msgstr ""
"Project-Id-Version: plone.app.discussion\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI +ZONE\n"
"PO-Revision-Date: 2011-12-14 15:33-0600\n"
"Last-Translator: Héctor Velarde <hector.velarde@gmail.com>\n"
"Language-Team: es <es@li.org>\n"
"PO-Revision-Date: 2014-12-11 16:07+0100\n"
"Last-Translator: Roberto Diaz <plone.team@upcnet.es>\n"
"Language-Team: Spanish <plone-i18n@lists.sourceforge.net>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
@ -16,103 +16,127 @@ msgstr ""
"Domain: plone.app.discussion\n"
"X-Is-Fallback-For: es-ar es-bo es-cl es-co es-cr es-do es-ec es-es es-sv es-gt es-hn es-mx es-ni es-pa es-py es-pe es-pr es-us es-uy es-ve\n"
#: ../comment.py:264
#: ../comment.py:359
msgid "A comment has been posted."
msgstr "Comentario añadido."
#: ../interfaces.py:257
#: ../interfaces.py:144
msgid "A comment id unique to this conversation"
msgstr "Un comentario de ID exclusivo para esta conversación"
#: ../browser/comments.py:67
#: ../browser/comments.py:72
msgid "Add a comment"
msgstr "Añadir un comentario"
#: ../browser/controlpanel.py:62
#: ../browser/controlpanel.py:75
msgid "Anonymous Comments"
msgstr "Comentarios anónimos"
#: ../interfaces.py:282
msgid "Author name (for display)"
msgstr "Nombre del autor (para mostrar)"
#: ../browser/comments.py:248
#: ../browser/controlpanel.py:80
#: ../browser/comments.py:275
#: ../browser/controlpanel.py:93
msgid "Cancel"
msgstr "Cancelar"
#: ../browser/controlpanel.py:76
#: ../interfaces.py:184
msgid "Captcha"
msgstr ""
#: ../browser/controlpanel.py:89
msgid "Changes saved"
msgstr "Cambios guardados"
#: ../browser/moderation.py:133
#: ../browser/moderation.py:186
msgid "Comment approved."
msgstr "Comentario aprobado."
#: ../browser/moderation.py:94
#: ../contentrules.py:92
msgid "Comment author email"
msgstr "Correo electrónico del autor del comentario"
#: ../contentrules.py:81
msgid "Comment author full name"
msgstr "Nombre completo del autor del comentario"
#: ../contentrules.py:70
msgid "Comment author user name"
msgstr "Nombre de usuario del autor del comentario"
#: ../browser/moderation.py:111
msgid "Comment deleted."
msgstr "Comentario eliminado."
#: ../browser/controlpanel.py:63
#: ../contentrules.py:48
msgid "Comment id"
msgstr "ID del comentario"
#: ../contentrules.py:59
msgid "Comment text"
msgstr "Texto del comentario"
#: ../browser/controlpanel.py:76
msgid "Commenter Image"
msgstr "Imagen del autor"
msgid "Commenting infrastructure for Plone"
msgstr "Infraestructura de comentarios para Plone"
#: ../interfaces.py:252
#: ../contentrules.py:47
msgid "Comments"
msgstr "Comentarios"
#: ../interfaces.py:139
msgid "Conversation"
msgstr "Conversación"
#: ../interfaces.py:283
#: ../interfaces.py:177
msgid "Creation date"
msgstr "Fecha de creación"
#: ../interfaces.py:162
msgid "Date of the most recent comment"
msgstr "Fecha del comentario más reciente"
#: ../interfaces.py:41
msgid "Date of the most recent public comment"
msgstr "Fecha del comentario publico más reciente"
#: ../vocabularies.py:44
msgid "Disabled"
msgstr "Desactivado"
#: ../browser/controlpanel.py:32
#: ../browser/controlpanel.py:33
msgid "Discussion settings"
msgstr "Ajustes de discusión"
#: ../browser/controlpanel.py:82
#: ../browser/controlpanel.py:95
msgid "Edit cancelled"
msgstr "Edición cancelada"
#: ../interfaces.py:269
#: ../interfaces.py:156
msgid "Email"
msgstr "Correo electrónico"
#: ../browser/controlpanel.py:61
#: ../browser/controlpanel.py:74
msgid "Enable Comments"
msgstr "Permitir comentarios"
#: ../interfaces.py:260
#: ../interfaces.py:147
msgid "Id of comment this comment is in reply to"
msgstr "ID del comentario este comentario es en respuesta a"
#: ../interfaces.py:274
#: ../interfaces.py:161
msgid "MIME type"
msgstr "Tipo MIME"
#: ../browser/controlpanel.py:65
#: ../browser/controlpanel.py:78
msgid "Moderator Email Notification"
msgstr "Notificación al moderador por correo electrónico"
#: ../interfaces.py:284
#: ../interfaces.py:178
msgid "Modification date"
msgstr "Fecha de modificación"
#: ../interfaces.py:254
#: ../interfaces.py:141
msgid "Name"
msgstr "Nombre"
#: ../interfaces.py:278
#: ../interfaces.py:170
msgid "Notify me of new comments via email."
msgstr "Recibir avisos por correo cuando haya nuevos comentarios."
@ -120,32 +144,44 @@ msgstr "Recibir avisos por correo cuando haya nuevos comentarios."
msgid "Plone Discussions"
msgstr "Plone Discussions"
#: ../interfaces.py:247
#: ../interfaces.py:134
msgid "Portal type"
msgstr "Tipo de objeto"
#: ../browser/controlpanel.py:69
#: ../browser/controlpanel.py:82
msgid "Save"
msgstr "Guardar"
#: ../interfaces.py:167
#: ../interfaces.py:46
msgid "The set of unique commentators (usernames)"
msgstr "Listado de usuarios que han comentado (nombres de usuario)"
#: ../interfaces.py:156
msgid "Total number of comments on this item"
msgstr "Número total de comentarios en este elemento"
#: ../interfaces.py:51
msgid "The set of unique commentators (usernames) of published_comments"
msgstr "El conjunto de comentaristas únicos (nombres de usuario) de published_comments"
#: ../browser/controlpanel.py:67
#: ../interfaces.py:35
msgid "Total number of public comments on this item"
msgstr "Total de comentarios públicos en este artículo"
#: ../comment.py:175
msgid "Transform '%s' => '%s' not available."
msgstr "Transformada '%s' => '%s' no disponible."
#: ../browser/controlpanel.py:80
msgid "User Email Notification"
msgstr "Notificaciones de correo para usuarios"
#: ../browser/comments.py:241
#: ../interfaces.py:176
msgid "Username of the commenter"
msgstr "Nombre de usuario del comentarista"
#: ../browser/comments.py:268
msgid "Your comment awaits moderator approval."
msgstr "Su comentario está pendiente de aprobación por el moderador."
#. Default: "Comment"
#: ../browser/comments.py:123
#: ../browser/comments.py:138
msgid "add_comment_button"
msgstr "Comentar"
@ -159,25 +195,55 @@ msgstr "Borrar"
msgid "bulkactions_publish"
msgstr "Aprobar"
#. Default: "Cancel"
#: ../browser/comment.py:97
msgid "cancel_form_button"
msgstr "Cancelar"
#. Default: "You can add a comment by filling out the form below. Plain text formatting. Web and email addresses are transformed into clickable links."
#: ../browser/comments.py:52
#: ../browser/comments.py:57
msgid "comment_description_intelligent_text"
msgstr "Puede agregar un comentario llenando el siguiente formulario. Formato de texto plano. Las direcciones web y de correo electrónico se transforman en vínculos."
#. Default: "You can add a comment by filling out the form below. Plain text formatting. You can use the Markdown syntax for links and images."
#: ../browser/comments.py:51
msgid "comment_description_markdown"
msgstr "Puede añadir un comentario rellenando el siguiente formulario. Formato texto plano. Puede utilizar la sintaxis de Markdown de enlaces e imágenes."
#. Default: "Comments are moderated."
#: ../browser/comments.py:58
#: ../browser/comments.py:63
msgid "comment_description_moderation_enabled"
msgstr "Los comentarios son moderados."
#. Default: "You can add a comment by filling out the form below. Plain text formatting."
#: ../browser/comments.py:47
#: ../browser/comments.py:46
msgid "comment_description_plain_text"
msgstr "Puede agregar un comentario llenando el sigueinte formulario. Formato de texto plano."
msgstr "Puede agregar un comentario llenando el siguiente formulario. Formato de texto plano."
#. Default: "${creator} on ${content}"
#: ../comment.py:46
#. Default: "Edit comment cancelled"
#: ../browser/comment.py:101
msgid "comment_edit_cancel_notification"
msgstr "Se ha cancelado la edición del comentario"
#. Default: "Comment was edited"
#: ../browser/comment.py:91
msgid "comment_edit_notification"
msgstr "Se ha editado el comentario"
#. Default: "${author_name} on ${content}"
#: ../comment.py:57
msgid "comment_title"
msgstr "${creator} sobre ${content}"
msgstr "${author_name} sobre ${content}"
#. Default: "Edit comment"
#: ../browser/comment.py:70
msgid "edit_comment_form_button"
msgstr "Editar comentario"
#. Default: "Edit comment"
#: ../browser/comment.py:54
msgid "edit_comment_form_title"
msgstr "Editar comentario"
#. Default: "Action"
#: ../browser/moderation.pt:85
@ -210,85 +276,107 @@ msgid "heading_moderate_comments"
msgstr "Moderar comentarios"
#. Default: "If selected, anonymous users are able to post comments without loggin in. It is highly recommended to use a captcha solution to prevent spam if this setting is enabled."
#: ../interfaces.py:38
#: ../interfaces.py:216
msgid "help_anonymous_comments"
msgstr "Si está seleccionado, los usuarios anónimos podrán añadir comentarios sin tener que iniciar una sesión. Recomendamos encarecidamente que utilice una solución Captcha para evitar el spam si esta opción está activada."
#. Default: "If selected, anonymous user will have to give their email."
#: ../interfaces.py:352
msgid "help_anonymous_email_enabled"
msgstr "Si se selecciona, el usuario anónimo tendrá que proporcionar su correo electrónico."
#. Default: "Use this setting to enable or disable Captcha validation for comments. Install plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet, or collective.z3cform.norobots if there are no options available."
#: ../interfaces.py:82
#: ../interfaces.py:288
msgid "help_captcha"
msgstr "Utilice esta opción para activar o desactivar Captcha para los comentarios. Instale plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet o collective.z3cform.norobots si no tiene ninguna opción disponible."
#. Default: "If selected, supports deleting of own comments for users with the 'Delete own comments' permission."
#: ../interfaces.py:260
msgid "help_delete_own_comment_enabled"
msgstr ""
#. Default: "Some discussion related settings are not located in the Discussion Control Panel.\nTo enable comments for a specific content type, go to the Types Control Panel of this type and choose \"Allow comments\".\nTo enable the moderation workflow for comments, go to the Types Control Panel, choose \"Comment\" and set workflow to \"Comment Review Workflow\"."
#: ../browser/controlpanel.py:33
#: ../browser/controlpanel.py:34
msgid "help_discussion_settings_editform"
msgstr ""
"Algunos de los ajustes sobre los comentarios no están en el Panel de Control de Discusiones.\n"
"Para activar comentarios para un tipo de objeto específico, vaya al Panel de Control de Tipos y elija 'Activar Comentarios'.\n"
"Para activar el workflow de moderación de comentarios, vaya al Panel de Control de Tipos, elija 'Comentario' y elija el 'Workflow de Moderación de Comentarios'."
#. Default: "If selected, supports editing of comments for users with the 'Edit comments' permission."
#: ../interfaces.py:249
#, fuzzy
msgid "help_edit_comment_enabled"
msgstr "Si se selecciona, permite la edición y eliminación de comentarios a los usuarios con el permiso 'Edita comentarios'"
#. Default: "If selected, users are able to post comments on the site. Though, you have to enable comments for specific content types, folders or content objects before users will be able to post comments."
#: ../interfaces.py:26
#: ../interfaces.py:202
msgid "help_globally_enabled"
msgstr "Si está seleccionado, se permite que los visitantes hagan comentarios en la web. Sin embargo, tiene que activar los comentarios para cada tipo de objeto específicamente antes de que se puedan añadir los comentarios."
#. Default: "If selected, comments will enter a 'Pending' state in which they are invisible to the public. A user with the 'Review comments' permission ('Reviewer' or 'Manager') can approve comments to make them visible to the public. If you want to enable a custom comment workflow, you have to go to the types control panel."
#: ../interfaces.py:50
#: ../interfaces.py:232
msgid "help_moderation_enabled"
msgstr "Si está seleccionado, los comentarios entraran en un estado 'Pendiente' en el cual ellos no son visibles para el público. Un usuario con el permiso 'Revisar comentarios' ('Revisor' o 'Administrador') puede aprobar los comentarios y hacerlos visibles al público. Si desea habilitar un workflow de comentarios diferente, puede hacerlo a través de la opción 'Configuración de Tipos' en el panel de control."
#. Default: "Address to which moderator notifications will be sent."
#: ../interfaces.py:118
#: ../interfaces.py:329
msgid "help_moderator_email"
msgstr "La dirección de correo electrónico a la cual se enviarán las notificaciones de moderación."
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be found in the 'Mail settings' control panel (Site 'From' address)"
#: ../interfaces.py:107
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be set below."
#: ../interfaces.py:315
msgid "help_moderator_notification_enabled"
msgstr "Si está seleccionado, se notifica al moderador cuando un nuevo comentario requiere de su atención. La dirección de correo electrónico del moderador se puede encontrar en la opción 'Configuración de correo' del panel de control (Dirección del remitente del sitio)"
#. Default: "If selected, an image of the user is shown next to the comment."
#: ../interfaces.py:97
#: ../interfaces.py:304
msgid "help_show_commenter_image"
msgstr "Si está seleccionado, se mostrará una imagen del autor junto al comentario."
#. Default: "Use this setting to choose if the comment text should be transformed in any way. You can choose between 'Plain text' and 'Intelligent text'. 'Intelligent text' converts plain text into HTML where line breaks and indentation is preserved, and web and email addresses are made into clickable links."
#: ../interfaces.py:66
#: ../interfaces.py:271
msgid "help_text_transform"
msgstr "Elija si el texto de los comentario será transformado de algún modo. Puede seleccionar entre 'Texto plano' y 'Texto inteligente'. 'Texto inteligente' convierte el texto plano en HTML, conservando los cambios de línea y la indentación, y transformando las direcciones web y de correo electrónico en vínculos."
#. Default: "If selected, users can choose to be notified of new comments by email."
#: ../interfaces.py:127
#: ../interfaces.py:341
msgid "help_user_notification_enabled"
msgstr "Si está seleccionado, los usuarios pueden solicitar recibir avisos por correo cuando haya nuevos comentarios."
#. Default: "Anonymous"
#: ../comment.py:156
#: ../browser/comments.pt:75
#: ../comment.py:193
msgid "label_anonymous"
msgstr "Anónimo"
#. Default: "Enable anonymous comments"
#: ../interfaces.py:36
#: ../interfaces.py:214
msgid "label_anonymous_comments"
msgstr "Permitir comentarios anónimos"
#. Default: "Enable anonymous email field"
#: ../interfaces.py:350
msgid "label_anonymous_email_enabled"
msgstr "Habilitar campo email de anónimos"
#. Default: "Apply"
#: ../browser/moderation.pt:71
msgid "label_apply"
msgstr "Aplicar"
#. Default: "Captcha"
#: ../interfaces.py:80
#: ../interfaces.py:286
msgid "label_captcha"
msgstr "Captcha"
#. Default: "Comment"
#: ../interfaces.py:275
#: ../interfaces.py:163
msgid "label_comment"
msgstr "Comentario"
#. Default: "Commenting has been disabled."
#: ../browser/comments.pt:130
#: ../browser/comments.pt:163
msgid "label_commenting_disabled"
msgstr "Los comentarios han sido inhabilitados."
@ -297,23 +385,33 @@ msgstr "Los comentarios han sido inhabilitados."
msgid "label_delete"
msgstr "Borrar"
#. Default: "Enable deleting own comments"
#: ../interfaces.py:258
msgid "label_delete_own_comment_enabled"
msgstr ""
#. Default: "Enable editing of comments"
#: ../interfaces.py:247
msgid "label_edit_comment_enabled"
msgstr "Activar la edición de comentarios"
#. Default: "Globally enable comments"
#: ../interfaces.py:24
#: ../interfaces.py:200
msgid "label_globally_enabled"
msgstr "Activar comentarios de forma global"
#. Default: "Enable comment moderation"
#: ../interfaces.py:48
#: ../interfaces.py:228
msgid "label_moderation_enabled"
msgstr "Habilitar la moderación de comentarios"
#. Default: "Moderator Email Address"
#: ../interfaces.py:117
#: ../interfaces.py:325
msgid "label_moderator_email"
msgstr "Dirección de correo electrónico del moderador"
#. Default: "Enable moderator email notification"
#: ../interfaces.py:105
#: ../interfaces.py:313
msgid "label_moderator_notification_enabled"
msgstr "Activar notificación al moderador"
@ -323,12 +421,12 @@ msgid "label_publish"
msgstr "Aprobar"
#. Default: "says:"
#: ../browser/comments.pt:74
#: ../browser/comments.pt:78
msgid "label_says"
msgstr "dice:"
#. Default: "Show commenter image"
#: ../interfaces.py:95
#: ../interfaces.py:302
msgid "label_show_commenter_image"
msgstr "Mostrar imagen del autor"
@ -338,22 +436,22 @@ msgid "label_show_full_comment_text"
msgstr "Mostrar texto completo"
#. Default: "Subject"
#: ../interfaces.py:271
#: ../interfaces.py:158
msgid "label_subject"
msgstr "Tema"
#. Default: "Comment text transform"
#: ../interfaces.py:64
#: ../interfaces.py:269
msgid "label_text_transform"
msgstr "Transformaciones aplicadas al texto del comentario"
#. Default: "Enable user email notification"
#: ../interfaces.py:125
#: ../interfaces.py:337
msgid "label_user_notification_enabled"
msgstr "Activar notificación de correo a los usuarios"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n"
#: ../comment.py:50
#: ../comment.py:61
msgid "mail_notification_message"
msgstr ""
"Se ha agregado un comentario a ${title} aquí: ${link}\n"
@ -363,7 +461,7 @@ msgstr ""
"---\n"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n\nApprove comment:\n${link_approve}\n\nDelete comment:\n${link_delete}\n"
#: ../comment.py:58
#: ../comment.py:69
msgid "mail_notification_message_moderator"
msgstr ""
"Se ha agregado un comentario a '${title}' aquí: ${link}\n"

View File

@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: plone.app.discussion\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI +ZONE\n"
"PO-Revision-Date: 2012-02-08 09:14+0100\n"
"PO-Revision-Date: 2013-11-14 09:09+0100\n"
"Last-Translator: Mikel Larreategi <mlarreategi@codesyntax.com>\n"
"Language-Team: eu <eu@li.org>\n"
"MIME-Version: 1.0\n"
@ -15,60 +15,84 @@ msgstr ""
"Domain: DOMAIN\n"
"X-Poedit-Language: Basque\n"
#: ../comment.py:294
#: ../comment.py:359
msgid "A comment has been posted."
msgstr "Erantzun bat argitaratu da."
#: ../interfaces.py:135
#: ../interfaces.py:144
msgid "A comment id unique to this conversation"
msgstr "Eztabaida honetarako bakarra den erantzunaren id-a."
#: ../browser/comments.py:73
#: ../browser/comments.py:72
msgid "Add a comment"
msgstr "Erantzuna gehitu"
#: ../browser/controlpanel.py:63
#: ../browser/controlpanel.py:75
msgid "Anonymous Comments"
msgstr "Erantzun anonimoak"
#: ../interfaces.py:160
msgid "Author name (for display)"
msgstr "Egilearen izena (argitaratuko dena)"
#: ../browser/comments.py:245
#: ../browser/controlpanel.py:81
#: ../browser/comments.py:275
#: ../browser/controlpanel.py:93
msgid "Cancel"
msgstr "Utzi"
#: ../browser/controlpanel.py:77
#: ../interfaces.py:184
msgid "Captcha"
msgstr ""
#: ../browser/controlpanel.py:89
msgid "Changes saved"
msgstr "Aldaketak gordeta"
#: ../browser/moderation.py:138
#: ../browser/moderation.py:186
msgid "Comment approved."
msgstr "Erantzuna onartuta."
#: ../browser/moderation.py:99
#: ../contentrules.py:92
msgid "Comment author email"
msgstr ""
#: ../contentrules.py:81
msgid "Comment author full name"
msgstr ""
#: ../contentrules.py:70
msgid "Comment author user name"
msgstr ""
#: ../browser/moderation.py:111
msgid "Comment deleted."
msgstr "Erantzuna ezabatuta."
#: ../browser/controlpanel.py:64
#: ../contentrules.py:48
msgid "Comment id"
msgstr ""
#: ../contentrules.py:59
msgid "Comment text"
msgstr ""
#: ../browser/controlpanel.py:76
msgid "Commenter Image"
msgstr "Erantzuna eman duenaren irudia."
msgid "Commenting infrastructure for Plone"
msgstr "Ploneren Erantzunen Azpiegitura"
#: ../interfaces.py:130
#: ../contentrules.py:47
msgid "Comments"
msgstr ""
#: ../interfaces.py:139
msgid "Conversation"
msgstr "Eztabaida"
#: ../interfaces.py:161
#: ../interfaces.py:177
msgid "Creation date"
msgstr "Sorrera data"
#: ../interfaces.py:40
msgid "Date of the most recent comment"
#: ../interfaces.py:41
msgid "Date of the most recent public comment"
msgstr "Azken erantzunaren data"
#: ../vocabularies.py:44
@ -79,39 +103,39 @@ msgstr "Desaktibatuta"
msgid "Discussion settings"
msgstr "Eztabaidaren ezarpenak"
#: ../browser/controlpanel.py:83
#: ../browser/controlpanel.py:95
msgid "Edit cancelled"
msgstr "Edizioa utzita"
#: ../interfaces.py:147
#: ../interfaces.py:156
msgid "Email"
msgstr "E-posta"
#: ../browser/controlpanel.py:62
#: ../browser/controlpanel.py:74
msgid "Enable Comments"
msgstr "Erantzunak aktibatu"
#: ../interfaces.py:138
#: ../interfaces.py:147
msgid "Id of comment this comment is in reply to"
msgstr "Erantzun honek erreferentzia egiten dion erantzunaren id-a"
#: ../interfaces.py:152
#: ../interfaces.py:161
msgid "MIME type"
msgstr "MIME mota"
#: ../browser/controlpanel.py:66
#: ../browser/controlpanel.py:78
msgid "Moderator Email Notification"
msgstr "Moderatzailea e-postaz abisatu"
#: ../interfaces.py:162
#: ../interfaces.py:178
msgid "Modification date"
msgstr "Aldaketa data"
#: ../interfaces.py:132
#: ../interfaces.py:141
msgid "Name"
msgstr "Izena"
#: ../interfaces.py:156
#: ../interfaces.py:170
msgid "Notify me of new comments via email."
msgstr "Erantzun berriak e-postaz bidali"
@ -119,32 +143,44 @@ msgstr "Erantzun berriak e-postaz bidali"
msgid "Plone Discussions"
msgstr "Plone Eztabaidak"
#: ../interfaces.py:125
#: ../interfaces.py:134
msgid "Portal type"
msgstr "Elementu mota"
#: ../browser/controlpanel.py:70
#: ../browser/controlpanel.py:82
msgid "Save"
msgstr "Gorde"
#: ../interfaces.py:45
#: ../interfaces.py:46
msgid "The set of unique commentators (usernames)"
msgstr "Erantzunak eman dituzten erabiltzaileak (erabiltzaile-izenak)"
#: ../interfaces.py:34
msgid "Total number of comments on this item"
msgstr "Elementu honen erantzun kopurua"
#: ../interfaces.py:51
msgid "The set of unique commentators (usernames) of published_comments"
msgstr "Erantzun-emaleen erabiltzaile izenak"
#: ../browser/controlpanel.py:68
#: ../interfaces.py:35
msgid "Total number of public comments on this item"
msgstr "Elementu honen erantzun publiko kopurua"
#: ../comment.py:175
msgid "Transform '%s' => '%s' not available."
msgstr "'%s' => '%s' eraldaketa ez dago erabilgarri."
#: ../browser/controlpanel.py:80
msgid "User Email Notification"
msgstr "E-posta abisuak"
#: ../browser/comments.py:238
#: ../interfaces.py:176
msgid "Username of the commenter"
msgstr "Erantzuna utzi duenaren erabiltzaile-izena"
#: ../browser/comments.py:268
msgid "Your comment awaits moderator approval."
msgstr "Zure erantzuna moderazio kolan dago."
#. Default: "Comment"
#: ../browser/comments.py:129
#: ../browser/comments.py:138
msgid "add_comment_button"
msgstr "Eman erantzuna"
@ -158,30 +194,55 @@ msgstr "Ezabatu"
msgid "bulkactions_publish"
msgstr "Onartu"
#. Default: "Cancel"
#: ../browser/comment.py:97
msgid "cancel_form_button"
msgstr ""
#. Default: "You can add a comment by filling out the form below. Plain text formatting. Web and email addresses are transformed into clickable links."
#: ../browser/comments.py:58
#: ../browser/comments.py:57
msgid "comment_description_intelligent_text"
msgstr "Erantzuna formulario hau betez utzi dezakezu. Formatua testu arruntarena da. Web eta e-posta helbideak automatikoki klikagarri agertuko dira."
#. Default: "You can add a comment by filling out the form below. Plain text formatting. You can use the Markdown syntax for links and images."
#: ../browser/comments.py:52
#: ../browser/comments.py:51
msgid "comment_description_markdown"
msgstr "Erantzuna formulario hau betez utzi dezakezu. Formatua testu arruntarena da. Lotura era irudientzat 'Markdown' sintaxia erabili dezakezu."
#. Default: "Comments are moderated."
#: ../browser/comments.py:64
#: ../browser/comments.py:63
msgid "comment_description_moderation_enabled"
msgstr "Erantzunak moderatuta daude."
#. Default: "You can add a comment by filling out the form below. Plain text formatting."
#: ../browser/comments.py:47
#: ../browser/comments.py:46
msgid "comment_description_plain_text"
msgstr "Erantzuna formulario hau betez utzi dezakezu. Formatua testu arruntarena da."
#. Default: "${creator} on ${content}"
#: ../comment.py:46
#. Default: "Edit comment cancelled"
#: ../browser/comment.py:101
msgid "comment_edit_cancel_notification"
msgstr ""
#. Default: "Comment was edited"
#: ../browser/comment.py:91
msgid "comment_edit_notification"
msgstr ""
#. Default: "${author_name} on ${content}"
#: ../comment.py:57
msgid "comment_title"
msgstr "${creator} ${content} buruz"
msgstr "${content} - ${creator}"
#. Default: "Edit comment"
#: ../browser/comment.py:70
msgid "edit_comment_form_button"
msgstr ""
#. Default: "Edit comment"
#: ../browser/comment.py:54
msgid "edit_comment_form_title"
msgstr ""
#. Default: "Action"
#: ../browser/moderation.pt:85
@ -214,15 +275,25 @@ msgid "heading_moderate_comments"
msgstr "Erantzunak moderatu"
#. Default: "If selected, anonymous users are able to post comments without loggin in. It is highly recommended to use a captcha solution to prevent spam if this setting is enabled."
#: ../interfaces.py:230
#: ../interfaces.py:216
msgid "help_anonymous_comments"
msgstr "Aukeratuta badago, erabiltzaile anonimoek erantzunak gehitu ditzakete login egin gabe. Berariaz gomendatzen dizugu Captcha kontrolen bat aktibatzea anonimoen erantzunak baimentzen badituzu."
#. Default: "If selected, anonymous user will have to give their email."
#: ../interfaces.py:352
msgid "help_anonymous_email_enabled"
msgstr "Aukeratuta badago, erabiltzaile anonimoek eposta helbidea idatzi beharko dute"
#. Default: "Use this setting to enable or disable Captcha validation for comments. Install plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet, or collective.z3cform.norobots if there are no options available."
#: ../interfaces.py:273
#: ../interfaces.py:288
msgid "help_captcha"
msgstr "Erabili aukera hau Captcha aktibatu edo desaktibatzeko. Instalatu plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet edo collective.z3cform.norobots aukerarik ez baldin badago."
#. Default: "If selected, supports deleting of own comments for users with the 'Delete own comments' permission."
#: ../interfaces.py:260
msgid "help_delete_own_comment_enabled"
msgstr ""
#. Default: "Some discussion related settings are not located in the Discussion Control Panel.\nTo enable comments for a specific content type, go to the Types Control Panel of this type and choose \"Allow comments\".\nTo enable the moderation workflow for comments, go to the Types Control Panel, choose \"Comment\" and set workflow to \"Comment Review Workflow\"."
#: ../browser/controlpanel.py:34
msgid "help_discussion_settings_editform"
@ -231,68 +302,80 @@ msgstr ""
"Elementu-mota jakin bati erantzunak aktibatzeko, joan elementu-moten kontrol panelera, aukeratu elementua eta aktibatu 'Erantzunak Baimendu'.\n"
"Erantzunen Moderazio Workflowa aktibatzeko, joan elementu-moten kontrol panelera, aukeratu 'Erantzuna' eta ezarri 'Erantzunen Moderazio Workflowa'."
#. Default: "If selected, supports editing of comments for users with the 'Edit comments' permission."
#: ../interfaces.py:249
msgid "help_edit_comment_enabled"
msgstr ""
#. Default: "If selected, users are able to post comments on the site. Though, you have to enable comments for specific content types, folders or content objects before users will be able to post comments."
#: ../interfaces.py:218
#: ../interfaces.py:202
msgid "help_globally_enabled"
msgstr "Aukeratuta badago, atarian erantzunak gehitu daitezke. Edonola ere, elementu-mota bakoitzarentzat erantzunak baimendu beharko dituzu erabiltzaileak erantzunak ematen hasi aurretik."
#. Default: "If selected, comments will enter a 'Pending' state in which they are invisible to the public. A user with the 'Review comments' permission ('Reviewer' or 'Manager') can approve comments to make them visible to the public. If you want to enable a custom comment workflow, you have to go to the types control panel."
#: ../interfaces.py:242
#: ../interfaces.py:232
msgid "help_moderation_enabled"
msgstr "Aukeratuta badago, erantzuna 'Zain' izeneko egoeran geldituko da eta ez da argitaratuko. 'Erantzunak errebisatu' baimena duten erabiltzaileek ('Zuzentzailea' edo 'Kudeatzailea') argitaratu ditzakete albisteak. Erantzunen worfklowa pertsonalizatu nahi baduzu, elementu-moten kontrol panelera joan zaitez."
#. Default: "Address to which moderator notifications will be sent."
#: ../interfaces.py:310
#: ../interfaces.py:329
msgid "help_moderator_email"
msgstr "Moderatzailearen notifikazioak bidali behar diren helbidea."
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be found in the 'Mail settings' control panel (Site 'From' address)"
#: ../interfaces.py:298
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be set below."
#: ../interfaces.py:315
#, fuzzy
msgid "help_moderator_notification_enabled"
msgstr "Aukeratuta badago, moderatzaileari e-posta abisua helduko zaio erantzun bat gehitzean. Moderatzailearen e-posta atariaren E-postaren konfigurazioan dago (Atariaren 'Nork' helbidea)"
#. Default: "If selected, an image of the user is shown next to the comment."
#: ../interfaces.py:288
#: ../interfaces.py:304
msgid "help_show_commenter_image"
msgstr "Aukeratuta badago, erantzuna eman duenaren irudi bat agertuko da testuaren ondoan."
#. Default: "Use this setting to choose if the comment text should be transformed in any way. You can choose between 'Plain text' and 'Intelligent text'. 'Intelligent text' converts plain text into HTML where line breaks and indentation is preserved, and web and email addresses are made into clickable links."
#: ../interfaces.py:257
#: ../interfaces.py:271
msgid "help_text_transform"
msgstr "Erabili aukera hau erantzunaren testua nolabait eraldatu behar bada. 'Testu arrunta' edo 'Testu argia'ren artean aukeratu dezakezu. 'Testu argia'-k testu arrunta HTML bihurtzen du lerro saltoak eta espazioak mantenduz, eta web helbideak eta e-postak klikagarri eginez."
#. Default: "If selected, users can choose to be notified of new comments by email."
#: ../interfaces.py:319
#: ../interfaces.py:341
msgid "help_user_notification_enabled"
msgstr "Aukeratuta badago, erabiltzaileek euren erantzunen erantzunak e-postaz jasotzea aktibatu dezakete."
#. Default: "Anonymous"
#: ../comment.py:158
#: ../browser/comments.pt:75
#: ../comment.py:193
msgid "label_anonymous"
msgstr "Anonimoak"
#. Default: "Enable anonymous comments"
#: ../interfaces.py:228
#: ../interfaces.py:214
msgid "label_anonymous_comments"
msgstr "Aktibatu erabiltzaile anonimoen erantzunak"
#. Default: "Enable anonymous email field"
#: ../interfaces.py:350
msgid "label_anonymous_email_enabled"
msgstr "Aktibatu anonimoentzat eposta eremua"
#. Default: "Apply"
#: ../browser/moderation.pt:71
msgid "label_apply"
msgstr "Aplikatu"
#. Default: "Captcha"
#: ../interfaces.py:271
#: ../interfaces.py:286
msgid "label_captcha"
msgstr "Captcha"
#. Default: "Comment"
#: ../interfaces.py:153
#: ../interfaces.py:163
msgid "label_comment"
msgstr "Erantzuna"
#. Default: "Commenting has been disabled."
#: ../browser/comments.pt:130
#: ../browser/comments.pt:163
msgid "label_commenting_disabled"
msgstr "Ezin da erantzunik gehitu."
@ -301,23 +384,33 @@ msgstr "Ezin da erantzunik gehitu."
msgid "label_delete"
msgstr "Ezabatu"
#. Default: "Enable deleting own comments"
#: ../interfaces.py:258
msgid "label_delete_own_comment_enabled"
msgstr ""
#. Default: "Enable editing of comments"
#: ../interfaces.py:247
msgid "label_edit_comment_enabled"
msgstr ""
#. Default: "Globally enable comments"
#: ../interfaces.py:216
#: ../interfaces.py:200
msgid "label_globally_enabled"
msgstr "Erantzunak globalki aktibatu"
#. Default: "Enable comment moderation"
#: ../interfaces.py:240
#: ../interfaces.py:228
msgid "label_moderation_enabled"
msgstr "Erantzunen moderazioa aktibatu."
#. Default: "Moderator Email Address"
#: ../interfaces.py:308
#: ../interfaces.py:325
msgid "label_moderator_email"
msgstr "Moderatzailearen e-posta helbidea"
#. Default: "Enable moderator email notification"
#: ../interfaces.py:296
#: ../interfaces.py:313
msgid "label_moderator_notification_enabled"
msgstr "Aktibatu moderatzaileari e-postaz abisatzea"
@ -327,12 +420,12 @@ msgid "label_publish"
msgstr "Argitaratu"
#. Default: "says:"
#: ../browser/comments.pt:74
#: ../browser/comments.pt:78
msgid "label_says"
msgstr "dio:"
#. Default: "Show commenter image"
#: ../interfaces.py:286
#: ../interfaces.py:302
msgid "label_show_commenter_image"
msgstr "Erantzuna eman duenaren irudia erakutsi"
@ -342,22 +435,22 @@ msgid "label_show_full_comment_text"
msgstr "Erakutsi testu osoa"
#. Default: "Subject"
#: ../interfaces.py:149
#: ../interfaces.py:158
msgid "label_subject"
msgstr "Gaia"
#. Default: "Comment text transform"
#: ../interfaces.py:255
#: ../interfaces.py:269
msgid "label_text_transform"
msgstr "Erantzunari aplikatu beharreko transformazioa"
#. Default: "Enable user email notification"
#: ../interfaces.py:317
#: ../interfaces.py:337
msgid "label_user_notification_enabled"
msgstr "Aktibatu erabiltzaileek e-postaz jakinaraztea"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n"
#: ../comment.py:50
#: ../comment.py:61
msgid "mail_notification_message"
msgstr ""
"Erantzuna berria:Izenburua: ${title} \n"
@ -367,7 +460,7 @@ msgstr ""
"--"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n\nApprove comment:\n${link_approve}\n\nDelete comment:\n${link_delete}\n"
#: ../comment.py:58
#: ../comment.py:69
msgid "mail_notification_message_moderator"
msgstr ""
"Erantzun berria:\n"

View File

@ -16,103 +16,127 @@ msgstr ""
"X-Poedit-Language: Finnish\n"
"X-Poedit-Country: FINLAND\n"
#: ../comment.py:264
#: ../comment.py:359
msgid "A comment has been posted."
msgstr ""
#: ../interfaces.py:257
#: ../interfaces.py:144
msgid "A comment id unique to this conversation"
msgstr "Tämän keskustelun sisällä uniikki tunniste"
#: ../browser/comments.py:67
#: ../browser/comments.py:72
msgid "Add a comment"
msgstr "Lisää viesti"
#: ../browser/controlpanel.py:62
#: ../browser/controlpanel.py:75
msgid "Anonymous Comments"
msgstr "Viestit tunnistamattomilta käyttäjiltä"
#: ../interfaces.py:282
msgid "Author name (for display)"
msgstr "Kirjoittajan nimi"
#: ../browser/comments.py:248
#: ../browser/controlpanel.py:80
#: ../browser/comments.py:275
#: ../browser/controlpanel.py:93
msgid "Cancel"
msgstr "Peru"
#: ../browser/controlpanel.py:76
#: ../interfaces.py:184
msgid "Captcha"
msgstr ""
#: ../browser/controlpanel.py:89
msgid "Changes saved"
msgstr ""
#: ../browser/moderation.py:133
#: ../browser/moderation.py:186
msgid "Comment approved."
msgstr "Viesti hyväksytty."
#: ../browser/moderation.py:94
#: ../contentrules.py:92
msgid "Comment author email"
msgstr ""
#: ../contentrules.py:81
msgid "Comment author full name"
msgstr ""
#: ../contentrules.py:70
msgid "Comment author user name"
msgstr ""
#: ../browser/moderation.py:111
msgid "Comment deleted."
msgstr "Viesti poistettu."
#: ../browser/controlpanel.py:63
#: ../contentrules.py:48
msgid "Comment id"
msgstr ""
#: ../contentrules.py:59
msgid "Comment text"
msgstr ""
#: ../browser/controlpanel.py:76
msgid "Commenter Image"
msgstr "Kirjoittajan kuva"
msgid "Commenting infrastructure for Plone"
msgstr "Plone:n kommentointi- ja keskustelutoiminnot"
#: ../interfaces.py:252
#: ../contentrules.py:47
msgid "Comments"
msgstr ""
#: ../interfaces.py:139
msgid "Conversation"
msgstr "Keskustelu"
#: ../interfaces.py:283
#: ../interfaces.py:177
msgid "Creation date"
msgstr "Luotu"
#: ../interfaces.py:162
msgid "Date of the most recent comment"
msgstr "Viimeisimmän viestin ajankohta"
#: ../interfaces.py:41
msgid "Date of the most recent public comment"
msgstr ""
#: ../vocabularies.py:44
msgid "Disabled"
msgstr "Ei käytössä"
#: ../browser/controlpanel.py:32
#: ../browser/controlpanel.py:33
msgid "Discussion settings"
msgstr "Kommentointi- ja keskustelutoimintojen asetukset"
#: ../browser/controlpanel.py:82
#: ../browser/controlpanel.py:95
msgid "Edit cancelled"
msgstr ""
#: ../interfaces.py:269
#: ../interfaces.py:156
msgid "Email"
msgstr "Sähköposti"
#: ../browser/controlpanel.py:61
#: ../browser/controlpanel.py:74
msgid "Enable Comments"
msgstr "Salli Kommentointi & Keskustelut"
#: ../interfaces.py:260
#: ../interfaces.py:147
msgid "Id of comment this comment is in reply to"
msgstr "Sen viestin tunniste johon tämä viesti vastaa"
#: ../interfaces.py:274
#: ../interfaces.py:161
msgid "MIME type"
msgstr "MIME-tyyppi"
#: ../browser/controlpanel.py:65
#: ../browser/controlpanel.py:78
msgid "Moderator Email Notification"
msgstr "Ilmoitukset sähköpostitse tarkistajille"
#: ../interfaces.py:284
#: ../interfaces.py:178
msgid "Modification date"
msgstr "Muutettu"
#: ../interfaces.py:254
#: ../interfaces.py:141
msgid "Name"
msgstr "Nimi"
#: ../interfaces.py:278
#: ../interfaces.py:170
msgid "Notify me of new comments via email."
msgstr ""
@ -120,32 +144,44 @@ msgstr ""
msgid "Plone Discussions"
msgstr "Kommentointi & Keskustelut (Plone Discussions)"
#: ../interfaces.py:247
#: ../interfaces.py:134
msgid "Portal type"
msgstr "Sisältötyyppi"
#: ../browser/controlpanel.py:69
#: ../browser/controlpanel.py:82
msgid "Save"
msgstr ""
#: ../interfaces.py:167
#: ../interfaces.py:46
msgid "The set of unique commentators (usernames)"
msgstr "Kirjoittajat (käyttäjätunnukset)"
#: ../interfaces.py:156
msgid "Total number of comments on this item"
msgstr "Viestien kokonaismäärä"
#: ../interfaces.py:51
msgid "The set of unique commentators (usernames) of published_comments"
msgstr ""
#: ../browser/controlpanel.py:67
#: ../interfaces.py:35
msgid "Total number of public comments on this item"
msgstr ""
#: ../comment.py:175
msgid "Transform '%s' => '%s' not available."
msgstr ""
#: ../browser/controlpanel.py:80
msgid "User Email Notification"
msgstr ""
#: ../browser/comments.py:241
#: ../interfaces.py:176
msgid "Username of the commenter"
msgstr ""
#: ../browser/comments.py:268
msgid "Your comment awaits moderator approval."
msgstr "Viestisi on vastaanotettu. Se tulee näkyviin heti kun ylläpito on hyväksynyt sen julkaistavaksi."
#. Default: "Comment"
#: ../browser/comments.py:123
#: ../browser/comments.py:138
msgid "add_comment_button"
msgstr "Lisää"
@ -159,26 +195,56 @@ msgstr "Poista valitut"
msgid "bulkactions_publish"
msgstr "Hyväksy valitut"
#. Default: "Cancel"
#: ../browser/comment.py:97
msgid "cancel_form_button"
msgstr ""
#. Default: "You can add a comment by filling out the form below. Plain text formatting. Web and email addresses are transformed into clickable links."
#: ../browser/comments.py:52
#: ../browser/comments.py:57
msgid "comment_description_intelligent_text"
msgstr ""
#. Default: "You can add a comment by filling out the form below. Plain text formatting. You can use the Markdown syntax for links and images."
#: ../browser/comments.py:51
msgid "comment_description_markdown"
msgstr ""
#. Default: "Comments are moderated."
#: ../browser/comments.py:58
#: ../browser/comments.py:63
msgid "comment_description_moderation_enabled"
msgstr ""
#. Default: "You can add a comment by filling out the form below. Plain text formatting."
#: ../browser/comments.py:47
#: ../browser/comments.py:46
msgid "comment_description_plain_text"
msgstr ""
#. Default: "${creator} on ${content}"
#: ../comment.py:46
#. Default: "Edit comment cancelled"
#: ../browser/comment.py:101
msgid "comment_edit_cancel_notification"
msgstr ""
#. Default: "Comment was edited"
#: ../browser/comment.py:91
msgid "comment_edit_notification"
msgstr ""
#. Default: "${author_name} on ${content}"
#: ../comment.py:57
msgid "comment_title"
msgstr ""
#. Default: "Edit comment"
#: ../browser/comment.py:70
msgid "edit_comment_form_button"
msgstr ""
#. Default: "Edit comment"
#: ../browser/comment.py:54
msgid "edit_comment_form_title"
msgstr ""
#. Default: "Action"
#: ../browser/moderation.pt:85
msgid "heading_action"
@ -210,85 +276,106 @@ msgid "heading_moderate_comments"
msgstr "Viestien esitarkistus"
#. Default: "If selected, anonymous users are able to post comments without loggin in. It is highly recommended to use a captcha solution to prevent spam if this setting is enabled."
#: ../interfaces.py:38
#: ../interfaces.py:216
msgid "help_anonymous_comments"
msgstr "Jos viestit tunnistamattomilta käyttäjiltä sallitaan, on erittäin suositeltavaa käyttää automaattisten roskapostittimien estintä (engl. captcha)."
#. Default: "If selected, anonymous user will have to give their email."
#: ../interfaces.py:352
msgid "help_anonymous_email_enabled"
msgstr ""
#. Default: "Use this setting to enable or disable Captcha validation for comments. Install plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet, or collective.z3cform.norobots if there are no options available."
#: ../interfaces.py:82
#: ../interfaces.py:288
#, fuzzy
msgid "help_captcha"
msgstr "Roskaviestiautomaattien estimen (engl. captcha) käyttö. Jos mitään estintä ei ole valittavissa, järjestelmään ei ole asennettu mitään estintä. Soveltuvia estimiä ovat plone.formwidget.captcha ('Captcha') ja plone.formwidget.recaptcha ('ReCapthca')."
#. Default: "If selected, supports deleting of own comments for users with the 'Delete own comments' permission."
#: ../interfaces.py:260
msgid "help_delete_own_comment_enabled"
msgstr ""
#. Default: "Some discussion related settings are not located in the Discussion Control Panel.\nTo enable comments for a specific content type, go to the Types Control Panel of this type and choose \"Allow comments\".\nTo enable the moderation workflow for comments, go to the Types Control Panel, choose \"Comment\" and set workflow to \"Comment Review Workflow\"."
#: ../browser/controlpanel.py:33
#: ../browser/controlpanel.py:34
msgid "help_discussion_settings_editform"
msgstr "Tarkista myös keskusteluun / kommentointiin liittyvät asetukset sisältötyyppien hallintapaneelissa ('Sisältötyypit')."
#. Default: "If selected, supports editing of comments for users with the 'Edit comments' permission."
#: ../interfaces.py:249
msgid "help_edit_comment_enabled"
msgstr ""
#. Default: "If selected, users are able to post comments on the site. Though, you have to enable comments for specific content types, folders or content objects before users will be able to post comments."
#: ../interfaces.py:26
#: ../interfaces.py:202
#, fuzzy
msgid "help_globally_enabled"
msgstr "Huomaa, että keskustelu/kommentointi pitää myös lisäksi erikseen asettaa päälle halutuille sisältötyypeille ja/tai yksittäisille sisällöille."
#. Default: "If selected, comments will enter a 'Pending' state in which they are invisible to the public. A user with the 'Review comments' permission ('Reviewer' or 'Manager') can approve comments to make them visible to the public. If you want to enable a custom comment workflow, you have to go to the types control panel."
#: ../interfaces.py:50
#: ../interfaces.py:232
msgid "help_moderation_enabled"
msgstr ""
#. Default: "Address to which moderator notifications will be sent."
#: ../interfaces.py:118
#: ../interfaces.py:329
msgid "help_moderator_email"
msgstr ""
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be found in the 'Mail settings' control panel (Site 'From' address)"
#: ../interfaces.py:107
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be set below."
#: ../interfaces.py:315
#, fuzzy
msgid "help_moderator_notification_enabled"
msgstr "Tarkistajana toimivalle ylläpitäjälle ilmoitetaan toimenpiteitä edellyttävistä viesteistä."
#. Default: "If selected, an image of the user is shown next to the comment."
#: ../interfaces.py:97
#: ../interfaces.py:304
msgid "help_show_commenter_image"
msgstr "Näytetäänkö kirjoittajan kuva viestin yhteydessä."
#. Default: "Use this setting to choose if the comment text should be transformed in any way. You can choose between 'Plain text' and 'Intelligent text'. 'Intelligent text' converts plain text into HTML where line breaks and indentation is preserved, and web and email addresses are made into clickable links."
#: ../interfaces.py:66
#: ../interfaces.py:271
msgid "help_text_transform"
msgstr ""
#. Default: "If selected, users can choose to be notified of new comments by email."
#: ../interfaces.py:127
#: ../interfaces.py:341
msgid "help_user_notification_enabled"
msgstr ""
#. Default: "Anonymous"
#: ../comment.py:156
#: ../browser/comments.pt:75
#: ../comment.py:193
msgid "label_anonymous"
msgstr ""
#. Default: "Enable anonymous comments"
#: ../interfaces.py:36
#: ../interfaces.py:214
msgid "label_anonymous_comments"
msgstr "Salli viestit tunnistamattomilta käyttäjiltä"
#. Default: "Enable anonymous email field"
#: ../interfaces.py:350
msgid "label_anonymous_email_enabled"
msgstr ""
#. Default: "Apply"
#: ../browser/moderation.pt:71
msgid "label_apply"
msgstr "toteuta"
#. Default: "Captcha"
#: ../interfaces.py:80
#: ../interfaces.py:286
msgid "label_captcha"
msgstr "Roskaviestien estin"
#. Default: "Comment"
#: ../interfaces.py:275
#: ../interfaces.py:163
msgid "label_comment"
msgstr "Viesti"
#. Default: "Commenting has been disabled."
#: ../browser/comments.pt:130
#: ../browser/comments.pt:163
msgid "label_commenting_disabled"
msgstr ""
@ -297,23 +384,33 @@ msgstr ""
msgid "label_delete"
msgstr "Poista"
#. Default: "Enable deleting own comments"
#: ../interfaces.py:258
msgid "label_delete_own_comment_enabled"
msgstr ""
#. Default: "Enable editing of comments"
#: ../interfaces.py:247
msgid "label_edit_comment_enabled"
msgstr ""
#. Default: "Globally enable comments"
#: ../interfaces.py:24
#: ../interfaces.py:200
msgid "label_globally_enabled"
msgstr "Keskustelu/kommentointitoiminnot käytössä"
#. Default: "Enable comment moderation"
#: ../interfaces.py:48
#: ../interfaces.py:228
msgid "label_moderation_enabled"
msgstr ""
#. Default: "Moderator Email Address"
#: ../interfaces.py:117
#: ../interfaces.py:325
msgid "label_moderator_email"
msgstr ""
#. Default: "Enable moderator email notification"
#: ../interfaces.py:105
#: ../interfaces.py:313
msgid "label_moderator_notification_enabled"
msgstr "Ilmoita viesteistä sähköpostitse ylläpitäjälle"
@ -323,12 +420,12 @@ msgid "label_publish"
msgstr "Hyväksy"
#. Default: "says:"
#: ../browser/comments.pt:74
#: ../browser/comments.pt:78
msgid "label_says"
msgstr ""
#. Default: "Show commenter image"
#: ../interfaces.py:95
#: ../interfaces.py:302
msgid "label_show_commenter_image"
msgstr "Näytä kirjoittajan kuva"
@ -338,27 +435,27 @@ msgid "label_show_full_comment_text"
msgstr "Näytä kokonaan"
#. Default: "Subject"
#: ../interfaces.py:271
#: ../interfaces.py:158
msgid "label_subject"
msgstr "Aihe"
#. Default: "Comment text transform"
#: ../interfaces.py:64
#: ../interfaces.py:269
msgid "label_text_transform"
msgstr ""
#. Default: "Enable user email notification"
#: ../interfaces.py:125
#: ../interfaces.py:337
msgid "label_user_notification_enabled"
msgstr ""
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n"
#: ../comment.py:50
#: ../comment.py:61
msgid "mail_notification_message"
msgstr ""
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n\nApprove comment:\n${link_approve}\n\nDelete comment:\n${link_delete}\n"
#: ../comment.py:58
#: ../comment.py:69
msgid "mail_notification_message_moderator"
msgstr ""

View File

@ -14,103 +14,127 @@ msgstr ""
"Preferred-Encodings: utf-8 latin1\n"
"Domain: plone.app.discussion\n"
#: ../comment.py:264
#: ../comment.py:359
msgid "A comment has been posted."
msgstr "Un commentaire a été posté."
#: ../interfaces.py:257
#: ../interfaces.py:144
msgid "A comment id unique to this conversation"
msgstr "Un id de commentaire unique pour cette conversation"
#: ../browser/comments.py:67
#: ../browser/comments.py:72
msgid "Add a comment"
msgstr "Ajouter un commentaire"
#: ../browser/controlpanel.py:62
#: ../browser/controlpanel.py:75
msgid "Anonymous Comments"
msgstr "Commentaires anonymes"
#: ../interfaces.py:282
msgid "Author name (for display)"
msgstr "Nom de l'auteur (pour l'affichage)"
#: ../browser/comments.py:248
#: ../browser/controlpanel.py:80
#: ../browser/comments.py:275
#: ../browser/controlpanel.py:93
msgid "Cancel"
msgstr "Annuler"
#: ../browser/controlpanel.py:76
#: ../interfaces.py:184
msgid "Captcha"
msgstr ""
#: ../browser/controlpanel.py:89
msgid "Changes saved"
msgstr "Modifications enregistrées"
#: ../browser/moderation.py:133
#: ../browser/moderation.py:186
msgid "Comment approved."
msgstr "Commentaire approuvé."
#: ../browser/moderation.py:94
#: ../contentrules.py:92
msgid "Comment author email"
msgstr ""
#: ../contentrules.py:81
msgid "Comment author full name"
msgstr ""
#: ../contentrules.py:70
msgid "Comment author user name"
msgstr ""
#: ../browser/moderation.py:111
msgid "Comment deleted."
msgstr "Commentaire supprimé."
#: ../browser/controlpanel.py:63
#: ../contentrules.py:48
msgid "Comment id"
msgstr ""
#: ../contentrules.py:59
msgid "Comment text"
msgstr ""
#: ../browser/controlpanel.py:76
msgid "Commenter Image"
msgstr "Portrait de l'utilisateur"
msgid "Commenting infrastructure for Plone"
msgstr "Infrastructure pour déposer des commentaires."
#: ../interfaces.py:252
#: ../contentrules.py:47
msgid "Comments"
msgstr ""
#: ../interfaces.py:139
msgid "Conversation"
msgstr "Conversation"
#: ../interfaces.py:283
#: ../interfaces.py:177
msgid "Creation date"
msgstr "Date de création"
#: ../interfaces.py:162
msgid "Date of the most recent comment"
msgstr "Date du commentaire le plus récent"
#: ../interfaces.py:41
msgid "Date of the most recent public comment"
msgstr "Date du dernier commentaire public"
#: ../vocabularies.py:44
msgid "Disabled"
msgstr "Désactivé"
#: ../browser/controlpanel.py:32
#: ../browser/controlpanel.py:33
msgid "Discussion settings"
msgstr "Paramètres des discussions"
#: ../browser/controlpanel.py:82
#: ../browser/controlpanel.py:95
msgid "Edit cancelled"
msgstr "Édition annulée"
#: ../interfaces.py:269
#: ../interfaces.py:156
msgid "Email"
msgstr "Adresse courriel"
#: ../browser/controlpanel.py:61
#: ../browser/controlpanel.py:74
msgid "Enable Comments"
msgstr "Activation des commentaires"
#: ../interfaces.py:260
#: ../interfaces.py:147
msgid "Id of comment this comment is in reply to"
msgstr "Id du commentaire dont ce commentaire répond"
#: ../interfaces.py:274
#: ../interfaces.py:161
msgid "MIME type"
msgstr "Type MIME"
#: ../browser/controlpanel.py:65
#: ../browser/controlpanel.py:78
msgid "Moderator Email Notification"
msgstr "Notification du modérateur par courriel"
#: ../interfaces.py:284
#: ../interfaces.py:178
msgid "Modification date"
msgstr "Date de modification"
#: ../interfaces.py:254
#: ../interfaces.py:141
msgid "Name"
msgstr "Nom"
#: ../interfaces.py:278
#: ../interfaces.py:170
msgid "Notify me of new comments via email."
msgstr "M'avertir des nouveaux commentaires par courriel."
@ -118,32 +142,44 @@ msgstr "M'avertir des nouveaux commentaires par courriel."
msgid "Plone Discussions"
msgstr "Plone Discussions"
#: ../interfaces.py:247
#: ../interfaces.py:134
msgid "Portal type"
msgstr "Portal type"
#: ../browser/controlpanel.py:69
#: ../browser/controlpanel.py:82
msgid "Save"
msgstr "Enregistrer"
#: ../interfaces.py:167
#: ../interfaces.py:46
msgid "The set of unique commentators (usernames)"
msgstr "L'ensemble des commentateurs uniques (identifiants)"
#: ../interfaces.py:156
msgid "Total number of comments on this item"
msgstr "Nombre total de commentaires pour cet élément"
#: ../interfaces.py:51
msgid "The set of unique commentators (usernames) of published_comments"
msgstr "L'ensemble des commentateurs uniques des commentaires publiés (identifiants)"
#: ../browser/controlpanel.py:67
#: ../interfaces.py:35
msgid "Total number of public comments on this item"
msgstr "Nombre total de commentaires publics sur cet élément"
#: ../comment.py:175
msgid "Transform '%s' => '%s' not available."
msgstr ""
#: ../browser/controlpanel.py:80
msgid "User Email Notification"
msgstr "Notification des utilisateurs par courriel"
#: ../browser/comments.py:241
#: ../interfaces.py:176
msgid "Username of the commenter"
msgstr "Identifiant de l'auteur du commentaire"
#: ../browser/comments.py:268
msgid "Your comment awaits moderator approval."
msgstr "Votre commentaire attend d'être modéré."
#. Default: "Comment"
#: ../browser/comments.py:123
#: ../browser/comments.py:138
msgid "add_comment_button"
msgstr "Commenter"
@ -157,25 +193,55 @@ msgstr "Supprimer"
msgid "bulkactions_publish"
msgstr "Approuver"
#. Default: "Cancel"
#: ../browser/comment.py:97
msgid "cancel_form_button"
msgstr ""
#. Default: "You can add a comment by filling out the form below. Plain text formatting. Web and email addresses are transformed into clickable links."
#: ../browser/comments.py:52
#: ../browser/comments.py:57
msgid "comment_description_intelligent_text"
msgstr "Vous pouvez ajouter un commentaire en complétant le formulaire ci-dessous. Le format doit être plain text. Les url et les courriels sont transformés en liens cliquables."
#. Default: "You can add a comment by filling out the form below. Plain text formatting. You can use the Markdown syntax for links and images."
#: ../browser/comments.py:51
msgid "comment_description_markdown"
msgstr "Vous pouvez ajouter un commentaire en complétant le formulaire ci-dessous. Format plein texte. Vous pouvez utiliser la syntaxe Markdown pour les liens et images."
#. Default: "Comments are moderated."
#: ../browser/comments.py:58
#: ../browser/comments.py:63
msgid "comment_description_moderation_enabled"
msgstr "Les commentaires sont modérés."
#. Default: "You can add a comment by filling out the form below. Plain text formatting."
#: ../browser/comments.py:47
#: ../browser/comments.py:46
msgid "comment_description_plain_text"
msgstr "Vous pouvez ajouter un commentaire en complétant le formulaire ci-dessous. Le format doit être plain text."
#. Default: "${creator} on ${content}"
#: ../comment.py:46
#. Default: "Edit comment cancelled"
#: ../browser/comment.py:101
msgid "comment_edit_cancel_notification"
msgstr ""
#. Default: "Comment was edited"
#: ../browser/comment.py:91
msgid "comment_edit_notification"
msgstr ""
#. Default: "${author_name} on ${content}"
#: ../comment.py:57
msgid "comment_title"
msgstr "${creator} sur ${content}"
msgstr "${author_name} sur ${content}"
#. Default: "Edit comment"
#: ../browser/comment.py:70
msgid "edit_comment_form_button"
msgstr ""
#. Default: "Edit comment"
#: ../browser/comment.py:54
msgid "edit_comment_form_title"
msgstr ""
#. Default: "Action"
#: ../browser/moderation.pt:85
@ -208,84 +274,106 @@ msgid "heading_moderate_comments"
msgstr "Modération des commentaires"
#. Default: "If selected, anonymous users are able to post comments without loggin in. It is highly recommended to use a captcha solution to prevent spam if this setting is enabled."
#: ../interfaces.py:38
#: ../interfaces.py:216
msgid "help_anonymous_comments"
msgstr "Si activé, les utilisateurs anonymes peuvent poster des commentaires sans se connecter. Il est fortement recommandé d'utiliser un captcha pour prévenir du spam si cette option est activée."
#. Default: "If selected, anonymous user will have to give their email."
#: ../interfaces.py:352
msgid "help_anonymous_email_enabled"
msgstr "Si cette case est cochée, les utilisateurs anonymes devront donner leur email."
#. Default: "Use this setting to enable or disable Captcha validation for comments. Install plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet, or collective.z3cform.norobots if there are no options available."
#: ../interfaces.py:82
#: ../interfaces.py:288
msgid "help_captcha"
msgstr "Utilisez cette option pour activer la validation par captcha pour les commentaires. Installez plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet ou collective.z3cform.norobots s'il n'y a aucune option de disponible."
#. Default: "If selected, supports deleting of own comments for users with the 'Delete own comments' permission."
#: ../interfaces.py:260
msgid "help_delete_own_comment_enabled"
msgstr ""
#. Default: "Some discussion related settings are not located in the Discussion Control Panel.\nTo enable comments for a specific content type, go to the Types Control Panel of this type and choose \"Allow comments\".\nTo enable the moderation workflow for comments, go to the Types Control Panel, choose \"Comment\" and set workflow to \"Comment Review Workflow\"."
#: ../browser/controlpanel.py:33
#: ../browser/controlpanel.py:34
msgid "help_discussion_settings_editform"
msgstr ""
"Certaines options liées aux discussions ne sont pas dans \"Paramètres des discussions\".\n"
"Pour activer les commentaires pour un type de contenu spécifique, allez dans \"Paramètres des types\", choisissez \"Commentaire\" et sélectionnez le workflow \"Workflow de modération des commentaires\"."
#. Default: "If selected, supports editing of comments for users with the 'Edit comments' permission."
#: ../interfaces.py:249
msgid "help_edit_comment_enabled"
msgstr ""
#. Default: "If selected, users are able to post comments on the site. Though, you have to enable comments for specific content types, folders or content objects before users will be able to post comments."
#: ../interfaces.py:26
#: ../interfaces.py:202
msgid "help_globally_enabled"
msgstr "Si vous cochez cette case, les utilisateurs pourront poster des commentaires sur ce site. Vous devez néanmoins activer les commentaires pour des types de contenu spécifiques, dossiers, ou éléments avant que les utilisateurs puissent poster des commentaires."
#. Default: "If selected, comments will enter a 'Pending' state in which they are invisible to the public. A user with the 'Review comments' permission ('Reviewer' or 'Manager') can approve comments to make them visible to the public. If you want to enable a custom comment workflow, you have to go to the types control panel."
#: ../interfaces.py:50
#: ../interfaces.py:232
msgid "help_moderation_enabled"
msgstr "Si cette case est cochée, les commentaires ajoutés seront mis 'en attente' et seront invisibles pour les visiteurs. Un utilisateur ayant la permission 'Review comments' (Modérateur ou Administrateur) peut approuver les commentaires pour les rendre visibles. Vous pouvez choisir un workflow spécifique pour les commentaires depuis le menu de configuration des types de contenu."
#. Default: "Address to which moderator notifications will be sent."
#: ../interfaces.py:118
#: ../interfaces.py:329
msgid "help_moderator_email"
msgstr "Addresse à laquelle les notifications de modération seront envoyées."
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be found in the 'Mail settings' control panel (Site 'From' address)"
#: ../interfaces.py:107
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be set below."
#: ../interfaces.py:315
#, fuzzy
msgid "help_moderator_notification_enabled"
msgstr "Si activé, le modérateur est notifié si un commentaire requiert une attention particulière. Le courriel du modérateur est défini sur la page 'Envoi de courriels' de la configuration du site (Adresse d'expéditeur des courriels)."
#. Default: "If selected, an image of the user is shown next to the comment."
#: ../interfaces.py:97
#: ../interfaces.py:304
msgid "help_show_commenter_image"
msgstr "Si activé, le portrait de l'utilisateur apparait à côté du commentaire."
#. Default: "Use this setting to choose if the comment text should be transformed in any way. You can choose between 'Plain text' and 'Intelligent text'. 'Intelligent text' converts plain text into HTML where line breaks and indentation is preserved, and web and email addresses are made into clickable links."
#: ../interfaces.py:66
#: ../interfaces.py:271
msgid "help_text_transform"
msgstr "Choisissez si le texte des commentaires doit être éventuellement transformé. Vous pouvez choisir entre 'Plain text' et 'Intelligent text'. Ce dernier convertit le texte en HTML, en préservant notamment les retours chariots et l'indentation, et en transformant les url et les addresses courriel en liens cliquables."
#. Default: "If selected, users can choose to be notified of new comments by email."
#: ../interfaces.py:127
#: ../interfaces.py:341
msgid "help_user_notification_enabled"
msgstr "Si vous cochez cette case, les utilisateurs pourront choisir d'être avertis par courriel des nouveaux commentaires."
#. Default: "Anonymous"
#: ../comment.py:156
#: ../browser/comments.pt:75
#: ../comment.py:193
msgid "label_anonymous"
msgstr "Anonyme"
#. Default: "Enable anonymous comments"
#: ../interfaces.py:36
#: ../interfaces.py:214
msgid "label_anonymous_comments"
msgstr "Activer les commentaires anonymes"
#. Default: "Enable anonymous email field"
#: ../interfaces.py:350
msgid "label_anonymous_email_enabled"
msgstr "Activer le champ email pour les anonymes"
#. Default: "Apply"
#: ../browser/moderation.pt:71
msgid "label_apply"
msgstr "Appliquer"
#. Default: "Captcha"
#: ../interfaces.py:80
#: ../interfaces.py:286
msgid "label_captcha"
msgstr "Captcha"
#. Default: "Comment"
#: ../interfaces.py:275
#: ../interfaces.py:163
msgid "label_comment"
msgstr "Commentaire"
#. Default: "Commenting has been disabled."
#: ../browser/comments.pt:130
#: ../browser/comments.pt:163
msgid "label_commenting_disabled"
msgstr "Les commentaires ont été désactivés."
@ -294,23 +382,33 @@ msgstr "Les commentaires ont été désactivés."
msgid "label_delete"
msgstr "Supprimer"
#. Default: "Enable deleting own comments"
#: ../interfaces.py:258
msgid "label_delete_own_comment_enabled"
msgstr ""
#. Default: "Enable editing of comments"
#: ../interfaces.py:247
msgid "label_edit_comment_enabled"
msgstr ""
#. Default: "Globally enable comments"
#: ../interfaces.py:24
#: ../interfaces.py:200
msgid "label_globally_enabled"
msgstr "Activer globalement les commentaires"
#. Default: "Enable comment moderation"
#: ../interfaces.py:48
#: ../interfaces.py:228
msgid "label_moderation_enabled"
msgstr "Activer la modération des commentaires"
#. Default: "Moderator Email Address"
#: ../interfaces.py:117
#: ../interfaces.py:325
msgid "label_moderator_email"
msgstr "Addresse courriel du modérateur"
#. Default: "Enable moderator email notification"
#: ../interfaces.py:105
#: ../interfaces.py:313
msgid "label_moderator_notification_enabled"
msgstr "Activer la notification du modérateur par courriel"
@ -320,12 +418,12 @@ msgid "label_publish"
msgstr "Approuver"
#. Default: "says:"
#: ../browser/comments.pt:74
#: ../browser/comments.pt:78
msgid "label_says"
msgstr "a écrit :"
#. Default: "Show commenter image"
#: ../interfaces.py:95
#: ../interfaces.py:302
msgid "label_show_commenter_image"
msgstr "Afficher le portrait de l'utilisateur"
@ -335,30 +433,45 @@ msgid "label_show_full_comment_text"
msgstr "afficher le texte complet du commentaire"
#. Default: "Subject"
#: ../interfaces.py:271
#: ../interfaces.py:158
msgid "label_subject"
msgstr "Sujet"
#. Default: "Comment text transform"
#: ../interfaces.py:64
#: ../interfaces.py:269
msgid "label_text_transform"
msgstr "Transformation du texte du commentaire"
#. Default: "Enable user email notification"
#: ../interfaces.py:125
#: ../interfaces.py:337
msgid "label_user_notification_enabled"
msgstr "Activer la notification par courriel des utilisateurs"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n"
#: ../comment.py:50
#, fuzzy
#: ../comment.py:61
msgid "mail_notification_message"
msgstr "Un commentaire a été ajouté sur '${title}' à cette addresse : ${link}"
msgstr ""
"Un commentaire a été ajouté sur '${title}' à cette addresse : ${link}\n"
"\n"
"---\n"
"${text}\n"
"---\n"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n\nApprove comment:\n${link_approve}\n\nDelete comment:\n${link_delete}\n"
#: ../comment.py:58
#: ../comment.py:69
msgid "mail_notification_message_moderator"
msgstr ""
"Un commentaire a été ajouté sur '${title}' à cette addresse : ${link}\n"
"\n"
"---\n"
"${text}\n"
"---\n"
"\n"
"Approver le commentaire :\n"
"${link_approve}\n"
"\n"
"Supprimer le commentaire :\n"
"${link_delete}\n"
#. Default: "enable the 'Comment Review Workflow' for the Comment content type"
#: ../browser/moderation.pt:33

View File

@ -4,9 +4,9 @@
msgid ""
msgstr ""
"Project-Id-Version: plone.app.discussion\n"
"POT-Creation-Date: 2011-04-22 17:12+0000\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI +ZONE\n"
"PO-Revision-Date: 2011-05-13 18:10+0100\n"
"Last-Translator: Giorgio Borelli <giorgio@giorgioborelli.it>\n"
"Last-Translator: Andrea Cecchi <andrea.cecchi@redturtle.it>\n"
"Language-Team: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
@ -18,103 +18,127 @@ msgstr ""
"Domain: plone.app.discussion\n"
"X-Is-Fallback-For: it-it it-ch it-sm it-hr it-si\n"
#: ../comment.py:264
#: ../comment.py:359
msgid "A comment has been posted."
msgstr "Un commento è stato inserito."
#: ../interfaces.py:257
#: ../interfaces.py:144
msgid "A comment id unique to this conversation"
msgstr "Id univoco del commento per questa conversazione"
#: ../browser/comments.py:67
#: ../browser/comments.py:72
msgid "Add a comment"
msgstr "Aggiungi un commento"
#: ../browser/controlpanel.py:62
#: ../browser/controlpanel.py:75
msgid "Anonymous Comments"
msgstr "Commenti Anonimi"
#: ../interfaces.py:282
msgid "Author name (for display)"
msgstr "Nome autore (per visualizzazione)"
#: ../browser/comments.py:248
#: ../browser/controlpanel.py:80
#: ../browser/comments.py:275
#: ../browser/controlpanel.py:93
msgid "Cancel"
msgstr "Annulla"
#: ../browser/controlpanel.py:76
#: ../interfaces.py:184
msgid "Captcha"
msgstr ""
#: ../browser/controlpanel.py:89
msgid "Changes saved"
msgstr "Modifiche salvate"
#: ../browser/moderation.py:133
#: ../browser/moderation.py:186
msgid "Comment approved."
msgstr "Commento approvato."
#: ../browser/moderation.py:94
#: ../contentrules.py:92
msgid "Comment author email"
msgstr "Email dell'autore del commento"
#: ../contentrules.py:81
msgid "Comment author full name"
msgstr "Nome dell'autore del commento"
#: ../contentrules.py:70
msgid "Comment author user name"
msgstr "Username dell'autore del commento"
#: ../browser/moderation.py:111
msgid "Comment deleted."
msgstr "Commento eliminato."
#: ../browser/controlpanel.py:63
#: ../contentrules.py:48
msgid "Comment id"
msgstr "Id commento"
#: ../contentrules.py:59
msgid "Comment text"
msgstr "Testo commento"
#: ../browser/controlpanel.py:76
msgid "Commenter Image"
msgstr "Immagine Commentatore"
msgid "Commenting infrastructure for Plone"
msgstr "Infrastruttura dei commenti per Plone"
#: ../interfaces.py:252
#: ../contentrules.py:47
msgid "Comments"
msgstr "Commenti"
#: ../interfaces.py:139
msgid "Conversation"
msgstr "Conversazione"
#: ../interfaces.py:283
#: ../interfaces.py:177
msgid "Creation date"
msgstr "Data di creazione"
#: ../interfaces.py:162
msgid "Date of the most recent comment"
msgstr "Data del commento più recente"
#: ../interfaces.py:41
msgid "Date of the most recent public comment"
msgstr "Data del commento pubblico più recente"
#: ../vocabularies.py:44
msgid "Disabled"
msgstr "Disabilitato"
#: ../browser/controlpanel.py:32
#: ../browser/controlpanel.py:33
msgid "Discussion settings"
msgstr "Impostazioni dei commenti"
#: ../browser/controlpanel.py:82
#: ../browser/controlpanel.py:95
msgid "Edit cancelled"
msgstr "Modifiche annullate"
#: ../interfaces.py:269
#: ../interfaces.py:156
msgid "Email"
msgstr "E-mail"
#: ../browser/controlpanel.py:61
#: ../browser/controlpanel.py:74
msgid "Enable Comments"
msgstr "Abilita commenti"
#: ../interfaces.py:260
#: ../interfaces.py:147
msgid "Id of comment this comment is in reply to"
msgstr "Id del commento a cui si risponde"
#: ../interfaces.py:274
#: ../interfaces.py:161
msgid "MIME type"
msgstr "MIME type"
#: ../browser/controlpanel.py:65
#: ../browser/controlpanel.py:78
msgid "Moderator Email Notification"
msgstr "Notifiche e-mail"
#: ../interfaces.py:284
#: ../interfaces.py:178
msgid "Modification date"
msgstr "Data di modifica"
#: ../interfaces.py:254
#: ../interfaces.py:141
msgid "Name"
msgstr "Nome"
#: ../interfaces.py:278
#: ../interfaces.py:170
msgid "Notify me of new comments via email."
msgstr "Notificami nuovi commenti via e-mail"
@ -122,32 +146,44 @@ msgstr "Notificami nuovi commenti via e-mail"
msgid "Plone Discussions"
msgstr "Supporto ai commenti Plone"
#: ../interfaces.py:247
#: ../interfaces.py:134
msgid "Portal type"
msgstr "Tipo di contenuto"
#: ../browser/controlpanel.py:69
#: ../browser/controlpanel.py:82
msgid "Save"
msgstr "Salva"
#: ../interfaces.py:167
#: ../interfaces.py:46
msgid "The set of unique commentators (usernames)"
msgstr "L'insieme unico dei commentatori (username)"
#: ../interfaces.py:156
msgid "Total number of comments on this item"
msgstr "Totale dei commenti per questo contenuto"
#: ../interfaces.py:51
msgid "The set of unique commentators (usernames) of published_comments"
msgstr "La lista di commentatori unici (username) dei commenti pubblicati"
#: ../browser/controlpanel.py:67
#: ../interfaces.py:35
msgid "Total number of public comments on this item"
msgstr "Numero totale di commenti pubblicati per questo contenuto"
#: ../comment.py:175
msgid "Transform '%s' => '%s' not available."
msgstr "Trasform '%s' => '%s' non disponibile."
#: ../browser/controlpanel.py:80
msgid "User Email Notification"
msgstr "Notifiche utenti via e-mail"
#: ../browser/comments.py:241
#: ../interfaces.py:176
msgid "Username of the commenter"
msgstr "Username dell'autore del commento"
#: ../browser/comments.py:268
msgid "Your comment awaits moderator approval."
msgstr "Il tuo commento è in attesa di approvazione"
#. Default: "Comment"
#: ../browser/comments.py:123
#: ../browser/comments.py:138
msgid "add_comment_button"
msgstr "Commenta"
@ -161,25 +197,55 @@ msgstr "Elimina"
msgid "bulkactions_publish"
msgstr "Approva"
#. Default: "You can add a comment by filling out the form below. Web and email addresses are transformed into clickable links."
#: ../browser/comments.py:52
#. Default: "Cancel"
#: ../browser/comment.py:97
msgid "cancel_form_button"
msgstr "Annulla"
#. Default: "You can add a comment by filling out the form below. Plain text formatting. Web and email addresses are transformed into clickable links."
#: ../browser/comments.py:57
msgid "comment_description_intelligent_text"
msgstr "Puoi aggiungere un commento compilando la form qui sotto. Utilizza testo semplice. Indirizzi web ed email saranno trasformati in collegamenti cliccabili."
#. Default: "You can add a comment by filling out the form below. Plain text formatting. You can use the Markdown syntax for links and images."
#: ../browser/comments.py:51
msgid "comment_description_markdown"
msgstr "Puoi aggiungere un commento compilando la form qui sotto. Utilizza testo semplice. Puoi utilizzare la sintassi Markdown per link ed immagini."
#. Default: "Comments are moderated."
#: ../browser/comments.py:58
#: ../browser/comments.py:63
msgid "comment_description_moderation_enabled"
msgstr "I commenti vengono moderati."
#. Default: "You can add a comment by filling out the form below."
#: ../browser/comments.py:47
#. Default: "You can add a comment by filling out the form below. Plain text formatting."
#: ../browser/comments.py:46
msgid "comment_description_plain_text"
msgstr "Puoi aggiungere un commento compilando la form sotto. Utilizza il testo semplice."
#. Default: "${creator} on ${content}"
#: ../comment.py:46
#. Default: "Edit comment cancelled"
#: ../browser/comment.py:101
msgid "comment_edit_cancel_notification"
msgstr "Modifica del commento annullata"
#. Default: "Comment was edited"
#: ../browser/comment.py:91
msgid "comment_edit_notification"
msgstr "Il commento è stato modificato"
#. Default: "${author_name} on ${content}"
#: ../comment.py:57
msgid "comment_title"
msgstr "${creator} su ${content}"
msgstr "${author_name} su ${content}"
#. Default: "Edit comment"
#: ../browser/comment.py:70
msgid "edit_comment_form_button"
msgstr "Modifica commento"
#. Default: "Edit comment"
#: ../browser/comment.py:54
msgid "edit_comment_form_title"
msgstr "Modifica commento"
#. Default: "Action"
#: ../browser/moderation.pt:85
@ -212,85 +278,107 @@ msgid "heading_moderate_comments"
msgstr "Moderazione commenti"
#. Default: "If selected, anonymous users are able to post comments without loggin in. It is highly recommended to use a captcha solution to prevent spam if this setting is enabled."
#: ../interfaces.py:38
#: ../interfaces.py:216
msgid "help_anonymous_comments"
msgstr "Se selezionato, gli utenti anonimi saranno in grado di inserire commenti senza autenticazione. E' altamente consigliato l'uso di captcha to prevenire spam se questa impostazione viene abilitata."
#. Default: "If selected, anonymous user will have to give their email."
#: ../interfaces.py:352
msgid "help_anonymous_email_enabled"
msgstr "Se selezionato, gli utenti anonimi dovranno fornire la loro email."
#. Default: "Use this setting to enable or disable Captcha validation for comments. Install plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet, or collective.z3cform.norobots if there are no options available."
#: ../interfaces.py:82
#: ../interfaces.py:288
msgid "help_captcha"
msgstr "Usa questa impostazione per abilitare o disabilitare la validazione tramite captcha. Se nessuna opzione di captcha è disponibile, installa plone.formwidget.captcha o plone.formwidget.recaptcha."
#. Default: "If selected, supports deleting of own comments for users with the 'Delete own comments' permission."
#: ../interfaces.py:260
msgid "help_delete_own_comment_enabled"
msgstr ""
#. Default: "Some discussion related settings are not located in the Discussion Control Panel.\nTo enable comments for a specific content type, go to the Types Control Panel of this type and choose \"Allow comments\".\nTo enable the moderation workflow for comments, go to the Types Control Panel, choose \"Comment\" and set workflow to \"Comment Review Workflow\"."
#: ../browser/controlpanel.py:33
#: ../browser/controlpanel.py:34
msgid "help_discussion_settings_editform"
msgstr ""
"Alcune impostazioni legate ai commenti non sono nel Pannello di controllo commenti.\n"
"Per abilitare i commenti per uno specifico tipo di contenuto, vai al Pannello dei Tipi di Contenuto per il tipo specifico e scegli 'abilita moderazione'.\n"
"Per abilitare il workflow per la moderazione dei commenti, vai al Pannello dei Tipi di Contenuto, scegli \"Comment\" e imposta il workflow \"Comment Review Workflow\"."
#. Default: "If selected, supports editing of comments for users with the 'Edit comments' permission."
#: ../interfaces.py:249
#, fuzzy
msgid "help_edit_comment_enabled"
msgstr "Se selezionato, verrà abilitato il supporto alla modifica dei commenti da parte degli utenti che hanno il permesso 'Edit comments'."
#. Default: "If selected, users are able to post comments on the site. Though, you have to enable comments for specific content types, folders or content objects before users will be able to post comments."
#: ../interfaces.py:26
#: ../interfaces.py:202
msgid "help_globally_enabled"
msgstr "Se selezionato, gli utenti saranno in grado di inserire commenti nel sito. Comunque, dovrai abilitare i commenti per specifici tipi di contenuto, cartelle o oggetti prima che gli utenti siano in grado di commentare."
#. Default: "If selected, comments will enter a 'Pending' state in which they are invisible to the public. A user with the 'Review comments' permission ('Reviewer' or 'Manager') can approve comments to make them visible to the public. If you want to enable a custom comment workflow, you have to go to the types control panel."
#: ../interfaces.py:50
#: ../interfaces.py:232
msgid "help_moderation_enabled"
msgstr "Se selezionato, i commenti verranno creati in stato 'In attesa' in cui sono non sono visibili pubblicamente. Un utento con il permesso 'Revisiona i commenti' ('Revisore' o 'Manager') possono approvare i commenti per renderli pubblici. Se si vuole abilitare un workflow personalizzato per i commenti, bisogna andare nel pannello di controllo dei tipi."
#. Default: "Address to which moderator notifications will be sent."
#: ../interfaces.py:118
#: ../interfaces.py:329
msgid "help_moderator_email"
msgstr "Indirizzo a cui verranno spedite le notifiche per la moderazione."
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be found in the 'Mail settings' control panel (Site 'From' address)"
#: ../interfaces.py:107
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be set below."
#: ../interfaces.py:315
msgid "help_moderator_notification_enabled"
msgstr "Se selezionato il moderatore riceverà una notifica se il commento dovrà necessita della sua attenzione. L'indirizzo email del moderatore può essere impostato nel pannello di controllo nella sezione 'Posta' (Indirizzo 'mittente' del sito)"
msgstr "Se selezionato il moderatore riceverà una notifica se il commento necessiterà della sua attenzione. L'indirizzo email del moderatore può essere impostato nel campo sottostante."
#. Default: "If selected, an image of the user is shown next to the comment."
#: ../interfaces.py:97
#: ../interfaces.py:304
msgid "help_show_commenter_image"
msgstr "Se selezionato, un'immagine dell'utente verrà mostrata a fianco dei commenti."
#. Default: "Use this setting to choose if the comment text should be transformed in any way. You can choose between 'Plain text' and 'Intelligent text'. 'Intelligent text' converts plain text into HTML where line breaks and indentation is preserved, and web and email addresses are made into clickable links."
#: ../interfaces.py:66
#: ../interfaces.py:271
msgid "help_text_transform"
msgstr "Utilizzare questa impostazione per scegliere se il testo del commento deve essere trasformato in qualche modo. E' possibile scegliere tra 'Plain text' e 'Testo intelligente'. 'Testo intelligente' converte il testo in HTML dove le interruzioni di linea e le indentazioni vengono preservate, e gli indirizzi web o email vengono trasformati in collegamenti cliccabili."
#. Default: "If selected, users can choose to be notified of new comments by email."
#: ../interfaces.py:127
#: ../interfaces.py:341
msgid "help_user_notification_enabled"
msgstr "Se selezionato, gli utenti possono scegliere di essere notificati ad ogni nuovo commenti via e-mail."
#. Default: "Anonymous"
#: ../comment.py:156
#: ../browser/comments.pt:75
#: ../comment.py:193
msgid "label_anonymous"
msgstr "Anonimo"
#. Default: "Enable anonymous comments"
#: ../interfaces.py:36
#: ../interfaces.py:214
msgid "label_anonymous_comments"
msgstr "Abilita i commenti agli utenti anonimi"
#. Default: "Enable anonymous email field"
#: ../interfaces.py:350
msgid "label_anonymous_email_enabled"
msgstr "Abilita campo email per utenti anonimi"
#. Default: "Apply"
#: ../browser/moderation.pt:71
msgid "label_apply"
msgstr "Applica"
#. Default: "Captcha"
#: ../interfaces.py:80
#: ../interfaces.py:286
msgid "label_captcha"
msgstr "Captcha"
#. Default: "Comment"
#: ../interfaces.py:275
#: ../interfaces.py:163
msgid "label_comment"
msgstr "Commento"
#. Default: "Commenting has been disabled."
#: ../browser/comments.pt:130
#: ../browser/comments.pt:163
msgid "label_commenting_disabled"
msgstr "I commenti sono stati disabilitati."
@ -299,23 +387,33 @@ msgstr "I commenti sono stati disabilitati."
msgid "label_delete"
msgstr "Elimina"
#. Default: "Enable deleting own comments"
#: ../interfaces.py:258
msgid "label_delete_own_comment_enabled"
msgstr ""
#. Default: "Enable editing of comments"
#: ../interfaces.py:247
msgid "label_edit_comment_enabled"
msgstr "Abilita la modifica dei commenti"
#. Default: "Globally enable comments"
#: ../interfaces.py:24
#: ../interfaces.py:200
msgid "label_globally_enabled"
msgstr "Abilita globalmente i commenti"
#. Default: "Enable comment moderation"
#: ../interfaces.py:48
#: ../interfaces.py:228
msgid "label_moderation_enabled"
msgstr "Abilita la moderazione dei commenti"
#. Default: "Moderator Email Address"
#: ../interfaces.py:117
#: ../interfaces.py:325
msgid "label_moderator_email"
msgstr "Indirizzo email del moderatore"
#. Default: "Enable moderator email notification"
#: ../interfaces.py:105
#: ../interfaces.py:313
msgid "label_moderator_notification_enabled"
msgstr "Abilita le notifiche ai moderatori"
@ -325,12 +423,12 @@ msgid "label_publish"
msgstr "Approva"
#. Default: "says:"
#: ../browser/comments.pt:74
#: ../browser/comments.pt:78
msgid "label_says"
msgstr ":"
#. Default: "Show commenter image"
#: ../interfaces.py:95
#: ../interfaces.py:302
msgid "label_show_commenter_image"
msgstr "Visualizza le immagini dei commentatori"
@ -340,29 +438,45 @@ msgid "label_show_full_comment_text"
msgstr "mostra testo completo del commento"
#. Default: "Subject"
#: ../interfaces.py:271
#: ../interfaces.py:158
msgid "label_subject"
msgstr "Oggetto"
#. Default: "Comment text transform"
#: ../interfaces.py:64
#: ../interfaces.py:269
msgid "label_text_transform"
msgstr "Transformazioni testo del commento"
#. Default: "Enable user email notification"
#: ../interfaces.py:125
#: ../interfaces.py:337
msgid "label_user_notification_enabled"
msgstr "Abilita notifica via e-mail"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n"
#: ../comment.py:50
#: ../comment.py:61
msgid "mail_notification_message"
msgstr "Un commento a '${title}' è stato inserito qui: ${link}\n\n---\n${text}\n---"
msgstr ""
"Un commento a '${title}' è stato inserito qui: ${link}\n"
"\n"
"---\n"
"${text}\n"
"---"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n\nApprove comment:\n${link_approve}\n\nDelete comment:\n${link_delete}\n"
#: ../comment.py:58
#: ../comment.py:69
msgid "mail_notification_message_moderator"
msgstr "Un commento su '${title}' è stato aggiunto qui: ${link}\n\n---\n${text}\n---\n\nApprova commento:\n${link_approve}\n\nElimina commento:\n${link_delete}"
msgstr ""
"Un commento su '${title}' è stato aggiunto qui: ${link}\n"
"\n"
"---\n"
"${text}\n"
"---\n"
"\n"
"Approva commento:\n"
"${link_approve}\n"
"\n"
"Elimina commento:\n"
"${link_delete}"
#. Default: "enable the 'Comment Review Workflow' for the Comment content type"
#: ../browser/moderation.pt:33

View File

@ -1,10 +1,11 @@
# Suzuki, Takanori <takanori@takanory.net> 2015
msgid ""
msgstr ""
"Project-Id-Version: plone.app.discussion\n"
"POT-Creation-Date: 2011-04-22 17:12+0000\n"
"PO-Revision-Date: 2010-01-28 15:00+0000\n"
"Last-Translator: Takeshi Yamamoto <tyam@mac.com>\n"
"Language-Team: Hanno Schlichting <hannosch@plone.org>\n"
"PO-Revision-Date: 2015-04-29 15:00+0000\n"
"Last-Translator: Suzuki, Takanori <takanori@takanory.net>\n"
"Language-Team: Plone Japanese Team <https://github.com/plonejp>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
@ -12,19 +13,19 @@ msgstr ""
"Language-Code: ja\n"
"Language-Name: Japanese\n"
#: ../comment.py:249
#: ../comment.py:359
msgid "A comment has been posted."
msgstr "コメントが投稿されました"
#: ../interfaces.py:282
#: ../interfaces.py:144
msgid "A comment id unique to this conversation"
msgstr "この会話上のユニークなコメントID"
#: ../browser/comments.py:71
#: ../browser/comments.py:72
msgid "Add a comment"
msgstr "コメントを追加"
#: ../browser/controlpanel.py:62
#: ../browser/controlpanel.py:75
msgid "Anonymous Comments"
msgstr "匿名コメント"
@ -32,83 +33,111 @@ msgstr "匿名コメント"
msgid "Author name (for display)"
msgstr "投稿者名(表示用)"
#: ../browser/comments.py:252
#: ../browser/controlpanel.py:80
#: ../browser/comments.py:275
#: ../browser/controlpanel.py:93
msgid "Cancel"
msgstr "取り消す"
#: ../browser/controlpanel.py:76
#: ../interfaces.py:184
msgid "Captcha"
msgstr ""
#: ../browser/controlpanel.py:89
msgid "Changes saved"
msgstr "変更が保存されました"
#: ../browser/moderation.py:141
#: ../browser/moderation.py:186
msgid "Comment approved."
msgstr "コメントが承認されました"
#: ../browser/moderation.py:102
#: ../contentrules.py:92
msgid "Comment author email"
msgstr ""
#: ../contentrules.py:81
msgid "Comment author full name"
msgstr ""
#: ../contentrules.py:70
msgid "Comment author user name"
msgstr ""
#: ../browser/moderation.py:111
msgid "Comment deleted."
msgstr "コメントが削除されました"
#: ../browser/controlpanel.py:63
#: ../contentrules.py:48
msgid "Comment id"
msgstr ""
#: ../contentrules.py:59
msgid "Comment text"
msgstr ""
#: ../browser/controlpanel.py:76
msgid "Commenter Image"
msgstr "投稿者者の画像"
msgid "Commenting infrastructure for Plone"
msgstr "Ploneのコメント基盤"
#: ../interfaces.py:277
#: ../contentrules.py:47
msgid "Comments"
msgstr ""
#: ../interfaces.py:139
msgid "Conversation"
msgstr "会話"
#: ../interfaces.py:308
#: ../interfaces.py:177
msgid "Creation date"
msgstr "作成日付"
#: ../interfaces.py:162
msgid "Date of the most recent comment"
#: ../interfaces.py:41
msgid "Date of the most recent public comment"
msgstr "最近のコメントの日付"
#: ../vocabularies.py:44
msgid "Disabled"
msgstr "無効になりました"
#: ../browser/controlpanel.py:32
#: ../browser/controlpanel.py:33
msgid "Discussion settings"
msgstr "議論の設定"
#: ../browser/controlpanel.py:82
#: ../browser/controlpanel.py:95
msgid "Edit cancelled"
msgstr "編集が取り消されました"
#: ../interfaces.py:294
#: ../interfaces.py:156
msgid "Email"
msgstr "メール"
#: ../browser/controlpanel.py:61
#: ../browser/controlpanel.py:74
msgid "Enable Comments"
msgstr "コメントを有効にする"
#: ../interfaces.py:285
#: ../interfaces.py:147
msgid "Id of comment this comment is in reply to"
msgstr "このコメントの返答先のコメントID"
#: ../interfaces.py:299
#: ../interfaces.py:161
msgid "MIME type"
msgstr "MIMEタイプ"
#: ../browser/controlpanel.py:65
#: ../browser/controlpanel.py:78
msgid "Moderator Email Notification"
msgstr "モデレーターへのメール通知"
#: ../interfaces.py:309
#: ../interfaces.py:178
msgid "Modification date"
msgstr "変更日付"
#: ../interfaces.py:279
#: ../interfaces.py:141
msgid "Name"
msgstr "名前"
#: ../interfaces.py:303
#: ../interfaces.py:170
msgid "Notify me of new comments via email."
msgstr "新しいコメントを私にメールで知らせる"
@ -116,32 +145,44 @@ msgstr "新しいコメントを私にメールで知らせる"
msgid "Plone Discussions"
msgstr "Plone議論"
#: ../interfaces.py:272
#: ../interfaces.py:134
msgid "Portal type"
msgstr "ポータルタイプ"
#: ../browser/controlpanel.py:69
#: ../browser/controlpanel.py:82
msgid "Save"
msgstr "保存"
#: ../interfaces.py:167
#: ../interfaces.py:46
msgid "The set of unique commentators (usernames)"
msgstr "ユニークな投稿者(ユーザ名)のセット"
#: ../interfaces.py:156
msgid "Total number of comments on this item"
msgstr "このアイテムでのコメントの合計数"
#: ../interfaces.py:51
msgid "The set of unique commentators (usernames) of published_comments"
msgstr ""
#: ../browser/controlpanel.py:67
#: ../interfaces.py:35
msgid "Total number of public comments on this item"
msgstr ""
#: ../comment.py:175
msgid "Transform '%s' => '%s' not available."
msgstr ""
#: ../browser/controlpanel.py:80
msgid "User Email Notification"
msgstr "ユーザへのメール通知"
#: ../browser/comments.py:245
#: ../interfaces.py:176
msgid "Username of the commenter"
msgstr ""
#: ../browser/comments.py:268
msgid "Your comment awaits moderator approval."
msgstr "コメントは司会の承認を待ちます"
#. Default: "Comment"
#: ../browser/comments.py:127
#: ../browser/comments.py:138
msgid "add_comment_button"
msgstr "コメント"
@ -155,26 +196,57 @@ msgstr "削除する"
msgid "bulkactions_publish"
msgstr "承認する"
#. Default: "Cancel"
#: ../browser/comment.py:97
msgid "cancel_form_button"
msgstr ""
#. Default: "You can add a comment by filling out the form below. Plain text formatting. Web and email addresses are transformed into clickable links."
#: ../browser/comments.py:56
#: ../browser/comments.py:57
msgid "comment_description_intelligent_text"
msgstr "下のフォームに書き込むことでコメントを追加するできます。Webアドレスやメールアドレスは、クリック可能なリンクに変換されます。"
#. Default: "You can add a comment by filling out the form below. Plain text formatting. You can use the Markdown syntax for links and images."
#: ../browser/comments.py:51
msgid "comment_description_markdown"
msgstr ""
#. Default: "Comments are moderated."
#: ../browser/comments.py:62
#: ../browser/comments.py:63
msgid "comment_description_moderation_enabled"
msgstr "コメントはモデレートされました"
#. Default: "You can add a comment by filling out the form below. Plain text formatting."
#: ../browser/comments.py:51
#: ../browser/comments.py:46
msgid "comment_description_plain_text"
msgstr "下のフォームに書き込むことでコメントを追加できます。プレーンテキスト形式です。"
#. Default: "${creator} on ${content}"
#: ../comment.py:50
#. Default: "Edit comment cancelled"
#: ../browser/comment.py:101
msgid "comment_edit_cancel_notification"
msgstr ""
#. Default: "Comment was edited"
#: ../browser/comment.py:91
msgid "comment_edit_notification"
msgstr ""
#. Default: "${author_name} on ${content}"
#: ../comment.py:57
#, fuzzy
msgid "comment_title"
msgstr "${creator} が ${content} にコメント"
#. Default: "Edit comment"
#: ../browser/comment.py:70
msgid "edit_comment_form_button"
msgstr ""
#. Default: "Edit comment"
#: ../browser/comment.py:54
msgid "edit_comment_form_title"
msgstr ""
#. Default: "Action"
#: ../browser/moderation.pt:85
msgid "heading_action"
@ -206,85 +278,107 @@ msgid "heading_moderate_comments"
msgstr "コメントをモデレート"
#. Default: "If selected, anonymous users are able to post comments without loggin in. It is highly recommended to use a captcha solution to prevent spam if this setting is enabled."
#: ../interfaces.py:38
#: ../interfaces.py:216
msgid "help_anonymous_comments"
msgstr "匿名ユーザがログインせずにコメントを投稿できます。この設定を有効にする場合は、CAPTCHAを使ってスパムを防ぐことをお勧めします。"
#. Default: "If selected, anonymous user will have to give their email."
#: ../interfaces.py:352
msgid "help_anonymous_email_enabled"
msgstr ""
#. Default: "Use this setting to enable or disable Captcha validation for comments. Install plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet, or collective.z3cform.norobots if there are no options available."
#: ../interfaces.py:82
#: ../interfaces.py:288
msgid "help_captcha"
msgstr "コメントでのCAPTCHAの有効/無効を設定します。CAPTCHAを有効にするには plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet または collective.z3cform.norobots をインストールしてください。"
#. Default: "If selected, supports deleting of own comments for users with the 'Delete own comments' permission."
#: ../interfaces.py:260
msgid "help_delete_own_comment_enabled"
msgstr ""
#. Default: "Some discussion related settings are not located in the Discussion Control Panel.\nTo enable comments for a specific content type, go to the Types Control Panel of this type and choose \"Allow comments\".\nTo enable the moderation workflow for comments, go to the Types Control Panel, choose \"Comment\" and set workflow to \"Comment Review Workflow\"."
#: ../browser/controlpanel.py:33
#: ../browser/controlpanel.py:34
msgid "help_discussion_settings_editform"
msgstr ""
"議論に関するいくつかの設定は、議論コントロールパネルに置かれていません。\n"
"特定のコンテンツタイプに対してコメントを有効にするには、タイプコントロールパネルでコンテンツタイプを選択し「コメントを許す」を選びます。\n"
"コメントに対してモデレーションワークフローを有効にするには、タイプコントロールパネルに行き、「コメント」を選び、ワークフローを「コメント審査ワークフロー」に設定します。"
#. Default: "If selected, supports editing of comments for users with the 'Edit comments' permission."
#: ../interfaces.py:249
msgid "help_edit_comment_enabled"
msgstr ""
#. Default: "If selected, users are able to post comments on the site. Though, you have to enable comments for specific content types, folders or content objects before users will be able to post comments."
#: ../interfaces.py:26
#: ../interfaces.py:202
msgid "help_globally_enabled"
msgstr "このサイトでユーザがコメントを投稿できるようになります。しかし、コメントを投稿できるようになるためには、さらにコンテンツタイプ、フォルダ、コンテンツオブジェクトに対して、コメントを有効にしなければなりません。"
#. Default: "If selected, comments will enter a 'Pending' state in which they are invisible to the public. A user with the 'Review comments' permission ('Reviewer' or 'Manager') can approve comments to make them visible to the public. If you want to enable a custom comment workflow, you have to go to the types control panel."
#: ../interfaces.py:50
#: ../interfaces.py:232
msgid "help_moderation_enabled"
msgstr "コメントは投稿されると非公開の「保留」状態になります。「コメントを審査」権限を持つユーザ(審査員または管理者)がコメントを承認して公開します。カスタムコメントワークフローを有効にするには、タイプコントロールパネルに行く必要があります。"
#. Default: "Address to which moderator notifications will be sent."
#: ../interfaces.py:118
#: ../interfaces.py:329
msgid "help_moderator_email"
msgstr "モデレータへの通知の送付先アドレス"
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be found in the 'Mail settings' control panel (Site 'From' address)"
#: ../interfaces.py:107
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be set below."
#: ../interfaces.py:315
#, fuzzy
msgid "help_moderator_notification_enabled"
msgstr "コメントが注意を要するものであるかどうか、モデレータは通知を受けるようになります。モデレータのメールアドレスはメール設定コントロールパネルの中のサイト「差出人」アドレスです。"
#. Default: "If selected, an image of the user is shown next to the comment."
#: ../interfaces.py:97
#: ../interfaces.py:304
msgid "help_show_commenter_image"
msgstr "コメントの横にユーザの画像が表示されます。"
#. Default: "Use this setting to choose if the comment text should be transformed in any way. You can choose between 'Plain text' and 'Intelligent text'. 'Intelligent text' converts plain text into HTML where line breaks and indentation is preserved, and web and email addresses are made into clickable links."
#: ../interfaces.py:66
#: ../interfaces.py:271
msgid "help_text_transform"
msgstr "コメントテキストの変換形式を選択します。「Intelligent text」はプレーンテキストをHTMLに変換します。改行とインデントは維持され、Webとメールアドレスはクリッカブルリンクになります。"
#. Default: "If selected, users can choose to be notified of new comments by email."
#: ../interfaces.py:127
#: ../interfaces.py:341
msgid "help_user_notification_enabled"
msgstr "ユーザは新しいコメントのメール通知を選択できるようになります。"
#. Default: "Anonymous"
#: ../comment.py:145
#: ../browser/comments.pt:75
#: ../comment.py:193
msgid "label_anonymous"
msgstr "匿名"
#. Default: "Enable anonymous comments"
#: ../interfaces.py:36
#: ../interfaces.py:214
msgid "label_anonymous_comments"
msgstr "匿名コメントを有効にする"
#. Default: "Enable anonymous email field"
#: ../interfaces.py:350
msgid "label_anonymous_email_enabled"
msgstr ""
#. Default: "Apply"
#: ../browser/moderation.pt:71
msgid "label_apply"
msgstr "適用"
#. Default: "Captcha"
#: ../interfaces.py:80
#: ../interfaces.py:286
msgid "label_captcha"
msgstr "キャプチャ"
#. Default: "Comment"
#: ../interfaces.py:300
#: ../interfaces.py:163
msgid "label_comment"
msgstr "コメント"
#. Default: "Commenting has been disabled."
#: ../browser/comments.pt:130
#: ../browser/comments.pt:163
msgid "label_commenting_disabled"
msgstr "コメント機能が無効になりました"
@ -293,23 +387,33 @@ msgstr "コメント機能が無効になりました"
msgid "label_delete"
msgstr "削除"
#. Default: "Enable deleting own comments"
#: ../interfaces.py:258
msgid "label_delete_own_comment_enabled"
msgstr ""
#. Default: "Enable editing of comments"
#: ../interfaces.py:247
msgid "label_edit_comment_enabled"
msgstr ""
#. Default: "Globally enable comments"
#: ../interfaces.py:24
#: ../interfaces.py:200
msgid "label_globally_enabled"
msgstr "サイト全体でコメントを有効にする"
#. Default: "Enable comment moderation"
#: ../interfaces.py:48
#: ../interfaces.py:228
msgid "label_moderation_enabled"
msgstr "コメントのモデレーションを有効にする"
#. Default: "Moderator Email Address"
#: ../interfaces.py:117
#: ../interfaces.py:325
msgid "label_moderator_email"
msgstr "モデレータのメールアドレス"
#. Default: "Enable moderator email notification"
#: ../interfaces.py:105
#: ../interfaces.py:313
msgid "label_moderator_notification_enabled"
msgstr "モデレータへのメール通知を有効にする"
@ -319,12 +423,12 @@ msgid "label_publish"
msgstr "承認"
#. Default: "says:"
#: ../browser/comments.pt:74
#: ../browser/comments.pt:78
msgid "label_says"
msgstr "さん:"
#. Default: "Show commenter image"
#: ../interfaces.py:95
#: ../interfaces.py:302
msgid "label_show_commenter_image"
msgstr "投稿者の画像を表示"
@ -334,22 +438,23 @@ msgid "label_show_full_comment_text"
msgstr "コメントテキストをすべて表示"
#. Default: "Subject"
#: ../interfaces.py:296
#: ../interfaces.py:158
msgid "label_subject"
msgstr "件名"
#. Default: "Comment text transform"
#: ../interfaces.py:64
#: ../interfaces.py:269
msgid "label_text_transform"
msgstr "テキスト変換"
#. Default: "Enable user email notification"
#: ../interfaces.py:125
#: ../interfaces.py:337
msgid "label_user_notification_enabled"
msgstr "ユーザへのメール通知を有効にする"
#. Default: "A comment on '${title}' has been posted here: ${link}"
#: ../comment.py:53
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n"
#: ../comment.py:61
#, fuzzy
msgid "mail_notification_message"
msgstr "'${title}' へのコメントが投稿されました: ${link}"
@ -358,6 +463,11 @@ msgstr "'${title}' へのコメントが投稿されました: ${link}"
msgid "mail_notification_message_moderator"
msgstr "${title} へのコメントが投稿されました: ${link}\n\n---\n${text}\n---\n\nコメントを承認:\n${link_approve}\n\nコメントを削除:\n${link_delete}\n"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n\nApprove comment:\n${link_approve}\n\nDelete comment:\n${link_delete}\n"
#: ../comment.py:69
msgid "mail_notification_message_moderator"
msgstr ""
#. Default: "enable the 'Comment Review Workflow' for the Comment content type"
#: ../browser/moderation.pt:33
msgid "message_enable_comment_workflow"

View File

@ -1,11 +1,10 @@
msgid ""
msgstr ""
"Project-Id-Version: plone.app.discussion\n"
"POT-Creation-Date: \n"
"POT-Creation-Date: YEAR-MO-DA HO:MI +ZONE\n"
"PO-Revision-Date: 2011-09-30 16:39+0100\n"
"Last-Translator: NFG Net Facilities Group BV <support@nfg.nl>\n"
"Language-Team: Nederlands <plone-i18n@lists.sourceforge.net>\n"
"Language: nl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
@ -14,137 +13,174 @@ msgstr ""
"Language-Name: Dutch\n"
"Preferred-Encodings: utf-8 latin1\n"
"Domain: plone.app.discussion\n"
"Language: nl\n"
#: ../comment.py:264
#: ../comment.py:359
msgid "A comment has been posted."
msgstr "Commentaar is geplaatst"
#: ../interfaces.py:257
#: ../interfaces.py:144
msgid "A comment id unique to this conversation"
msgstr "Een unieke ID voor dit commentaar"
#: ../browser/comments.py:67
#: ../browser/comments.py:72
msgid "Add a comment"
msgstr "Voeg opmerking toe"
#: ../browser/controlpanel.py:62
#: ../browser/controlpanel.py:75
msgid "Anonymous Comments"
msgstr "Anoniem commentaar"
#: ../interfaces.py:282
msgid "Author name (for display)"
msgstr "Auteur"
#: ../browser/comments.py:248
#: ../browser/controlpanel.py:80
#: ../browser/comments.py:275
#: ../browser/controlpanel.py:93
msgid "Cancel"
msgstr "Annuleren"
#: ../browser/controlpanel.py:76
#: ../interfaces.py:184
msgid "Captcha"
msgstr ""
#: ../browser/controlpanel.py:89
msgid "Changes saved"
msgstr "Wijzigingen opgeslagen"
#: ../browser/moderation.py:133
#: ../browser/moderation.py:186
msgid "Comment approved."
msgstr "Commentaar goedgekeurd"
#: ../browser/moderation.py:94
#: ../contentrules.py:92
msgid "Comment author email"
msgstr ""
#: ../contentrules.py:81
msgid "Comment author full name"
msgstr ""
#: ../contentrules.py:70
msgid "Comment author user name"
msgstr ""
#: ../browser/moderation.py:111
msgid "Comment deleted."
msgstr "Commentaar verwijderd"
#: ../browser/controlpanel.py:63
#: ../contentrules.py:48
msgid "Comment id"
msgstr ""
#: ../contentrules.py:59
msgid "Comment text"
msgstr ""
#: ../browser/controlpanel.py:76
msgid "Commenter Image"
msgstr "Profielfoto commentator"
msgid "Commenting infrastructure for Plone"
msgstr "Reactie infrastructuur voor Plone"
#: ../interfaces.py:252
#: ../contentrules.py:47
msgid "Comments"
msgstr ""
#: ../interfaces.py:139
msgid "Conversation"
msgstr "Conversatie"
#: ../interfaces.py:283
#: ../interfaces.py:177
msgid "Creation date"
msgstr "Aanmaakdatum"
#: ../interfaces.py:162
msgid "Date of the most recent comment"
msgstr "Datum van het laatste commentaar"
#: ../interfaces.py:41
msgid "Date of the most recent public comment"
msgstr ""
#: ../vocabularies.py:44
msgid "Disabled"
msgstr "Uitgeschakeld"
#: ../browser/controlpanel.py:32
#: ../browser/controlpanel.py:33
msgid "Discussion settings"
msgstr "Discussie instellingen"
#: ../browser/controlpanel.py:82
#: ../browser/controlpanel.py:95
msgid "Edit cancelled"
msgstr "Bewerken geannulleerd."
#: ../interfaces.py:269
#: ../interfaces.py:156
msgid "Email"
msgstr "E-mail"
#: ../browser/controlpanel.py:61
#: ../browser/controlpanel.py:74
msgid "Enable Comments"
msgstr "Commentaar toestaan"
#: ../interfaces.py:260
#: ../interfaces.py:147
msgid "Id of comment this comment is in reply to"
msgstr "Id van commentaar waarop deze commentaar reageert"
#: ../interfaces.py:274
#: ../interfaces.py:161
msgid "MIME type"
msgstr "MIME-type"
#: ../browser/controlpanel.py:65
#: ../browser/controlpanel.py:78
msgid "Moderator Email Notification"
msgstr "E-mail notificatie voor de redactie"
#: ../interfaces.py:284
#: ../interfaces.py:178
msgid "Modification date"
msgstr "Wijzigingsdatum"
#: ../interfaces.py:254
#: ../interfaces.py:141
msgid "Name"
msgstr "Naam"
#: ../interfaces.py:278
#: ../interfaces.py:170
msgid "Notify me of new comments via email."
msgstr "Hou me middels e-mail op de hoogte van nieuwe commentaar."
#: plone.app.discussion/plone/app/discussion/configure.zcml
#: ./plone.app.discussion/plone/app/discussion/configure.zcml
msgid "Plone Discussions"
msgstr "Plone Discussies"
#: ../interfaces.py:247
#: ../interfaces.py:134
msgid "Portal type"
msgstr "type"
#: ../browser/controlpanel.py:69
#: ../browser/controlpanel.py:82
msgid "Save"
msgstr "Bewaren"
#: ../interfaces.py:167
#: ../interfaces.py:46
msgid "The set of unique commentators (usernames)"
msgstr "Lijst van commentatoren (gebruikernamen)"
#: ../interfaces.py:156
msgid "Total number of comments on this item"
msgstr "Totaal aantal commentaar op dit item"
#: ../interfaces.py:51
msgid "The set of unique commentators (usernames) of published_comments"
msgstr ""
#: ../browser/controlpanel.py:67
#: ../interfaces.py:35
msgid "Total number of public comments on this item"
msgstr ""
#: ../comment.py:175
msgid "Transform '%s' => '%s' not available."
msgstr ""
#: ../browser/controlpanel.py:80
msgid "User Email Notification"
msgstr "Gebruker E-mail Notificatie"
#: ../browser/comments.py:241
#: ../interfaces.py:176
msgid "Username of the commenter"
msgstr ""
#: ../browser/comments.py:268
msgid "Your comment awaits moderator approval."
msgstr "Je commentaar zal geplaatst worden na goedkeuring."
#. Default: "Comment"
#: ../browser/comments.py:123
#: ../browser/comments.py:138
msgid "add_comment_button"
msgstr "Commentaar toevoegen"
@ -158,26 +194,57 @@ msgstr "Verwijderen"
msgid "bulkactions_publish"
msgstr "Publiceren"
#. Default: "Cancel"
#: ../browser/comment.py:97
msgid "cancel_form_button"
msgstr ""
#. Default: "You can add a comment by filling out the form below. Plain text formatting. Web and email addresses are transformed into clickable links."
#: ../browser/comments.py:52
#: ../browser/comments.py:57
msgid "comment_description_intelligent_text"
msgstr "U kunt commentaar toevoegen door onderstaand formulier in te vullen. Platte tekst formaat. Web en e-mail adressen worden omgezet in klikbare links."
#. Default: "You can add a comment by filling out the form below. Plain text formatting. You can use the Markdown syntax for links and images."
#: ../browser/comments.py:51
msgid "comment_description_markdown"
msgstr ""
#. Default: "Comments are moderated."
#: ../browser/comments.py:58
#: ../browser/comments.py:63
msgid "comment_description_moderation_enabled"
msgstr "Commentaren zijn gemodereerd."
#. Default: "You can add a comment by filling out the form below. Plain text formatting."
#: ../browser/comments.py:47
#: ../browser/comments.py:46
msgid "comment_description_plain_text"
msgstr "U kunt commentaar toevoegen door onderstaand formulier in te vullen. Platte tekst formaat."
#. Default: "${creator} on ${content}"
#: ../comment.py:46
#. Default: "Edit comment cancelled"
#: ../browser/comment.py:101
msgid "comment_edit_cancel_notification"
msgstr ""
#. Default: "Comment was edited"
#: ../browser/comment.py:91
msgid "comment_edit_notification"
msgstr ""
#. Default: "${author_name} on ${content}"
#: ../comment.py:57
#, fuzzy
msgid "comment_title"
msgstr "${creator} over ${content}"
#. Default: "Edit comment"
#: ../browser/comment.py:70
msgid "edit_comment_form_button"
msgstr ""
#. Default: "Edit comment"
#: ../browser/comment.py:54
msgid "edit_comment_form_title"
msgstr ""
#. Default: "Action"
#: ../browser/moderation.pt:85
msgid "heading_action"
@ -209,82 +276,104 @@ msgid "heading_moderate_comments"
msgstr "Commentaar modereren"
#. Default: "If selected, anonymous users are able to post comments without loggin in. It is highly recommended to use a captcha solution to prevent spam if this setting is enabled."
#: ../interfaces.py:38
#: ../interfaces.py:216
msgid "help_anonymous_comments"
msgstr "Indien geselecteerd, anonieme bezoekers kunnen commentaar achterlaten zonder in te loggen. Het is aanbevolen om de captcha-oplossing te gebruiken om spam te voorkomen als deze optie is ingeschakeld."
#. Default: "If selected, anonymous user will have to give their email."
#: ../interfaces.py:352
msgid "help_anonymous_email_enabled"
msgstr ""
#. Default: "Use this setting to enable or disable Captcha validation for comments. Install plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet, or collective.z3cform.norobots if there are no options available."
#: ../interfaces.py:82
#: ../interfaces.py:288
msgid "help_captcha"
msgstr "Indien geselecteerd, Captcha validatie wordt gebruikt voor het commentaar. Installeer plone.formwidget of plone.formwidget.recaptcha als er geen opties beschikbaar zijn."
#. Default: "If selected, supports deleting of own comments for users with the 'Delete own comments' permission."
#: ../interfaces.py:260
msgid "help_delete_own_comment_enabled"
msgstr ""
#. Default: "Some discussion related settings are not located in the Discussion Control Panel.\nTo enable comments for a specific content type, go to the Types Control Panel of this type and choose \"Allow comments\".\nTo enable the moderation workflow for comments, go to the Types Control Panel, choose \"Comment\" and set workflow to \"Comment Review Workflow\"."
#: ../browser/controlpanel.py:33
#: ../browser/controlpanel.py:34
msgid "help_discussion_settings_editform"
msgstr "Sommige discussie instellingen staan niet op deze pagina. Om commentaar in te schakelen voor een specifiek content-type, ga naar het Typen instellingenscherm van het betreffende type en kies 'commentaar toestaan'. Om de moderatie-workflow in te schakelen, ga naar het Typen instellingenscherm en kies het type 'Comment' stel de 'Comment Review Workflow' in."
#. Default: "If selected, supports editing of comments for users with the 'Edit comments' permission."
#: ../interfaces.py:249
msgid "help_edit_comment_enabled"
msgstr ""
#. Default: "If selected, users are able to post comments on the site. Though, you have to enable comments for specific content types, folders or content objects before users will be able to post comments."
#: ../interfaces.py:26
#: ../interfaces.py:202
msgid "help_globally_enabled"
msgstr "Indien geselecteerd, gebruikers kunnen commentaar plaatsen op de site. Het kan zijn dat commentaar voor een specifiek content-type ingeschakeld moet worden voordat commentaar mogelijk is."
#. Default: "If selected, comments will enter a 'Pending' state in which they are invisible to the public. A user with the 'Review comments' permission ('Reviewer' or 'Manager') can approve comments to make them visible to the public. If you want to enable a custom comment workflow, you have to go to the types control panel."
#: ../interfaces.py:50
#: ../interfaces.py:232
msgid "help_moderation_enabled"
msgstr "Indien geselecteerd, de moderator zal ingelicht worden als een commentaar aandacht nodig heeft."
#. Default: "Address to which moderator notifications will be sent."
#: ../interfaces.py:118
#: ../interfaces.py:329
msgid "help_moderator_email"
msgstr "Emailadres van de moderator naar wie een notificatie zal worden gestuurd."
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be found in the 'Mail settings' control panel (Site 'From' address)"
#: ../interfaces.py:107
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be set below."
#: ../interfaces.py:315
#, fuzzy
msgid "help_moderator_notification_enabled"
msgstr "Indien geselecteerd, de moderator zal ingelicht worden als een commentaar aandacht nodig heeft."
#. Default: "If selected, an image of the user is shown next to the comment."
#: ../interfaces.py:97
#: ../interfaces.py:304
msgid "help_show_commenter_image"
msgstr "Indien geselecteerd, de profielfoto van een gebruiker wordt naast het commentaar getoond."
#. Default: "Use this setting to choose if the comment text should be transformed in any way. You can choose between 'Plain text' and 'Intelligent text'. 'Intelligent text' converts plain text into HTML where line breaks and indentation is preserved, and web and email addresses are made into clickable links."
#: ../interfaces.py:66
#: ../interfaces.py:271
msgid "help_text_transform"
msgstr "Gebruik deze instelling om ervoor te kiezen of de commentaar tekst getransformeerd moet worden. U kunt kiezen uit 'Platte tekst' en 'Intelligente tekst'. 'Intelligente tekst' zet platte tekst om in HTML waarbij nieuwe regels en inspringen worden gehandhaaft, en waarbij web en e-mail adressen in klikbare links worden omgezet."
#. Default: "If selected, users can choose to be notified of new comments by email."
#: ../interfaces.py:127
#: ../interfaces.py:341
msgid "help_user_notification_enabled"
msgstr "Indien geselecteerd kunnen gebruikers ervoor kiezen per e-mail bericht te ontvangen van nieuwe commentaar."
#. Default: "Anonymous"
#: ../comment.py:156
#: ../browser/comments.pt:75
#: ../comment.py:193
msgid "label_anonymous"
msgstr "Anoniem"
#. Default: "Enable anonymous comments"
#: ../interfaces.py:36
#: ../interfaces.py:214
msgid "label_anonymous_comments"
msgstr "Anoniem commentariëren inschakelen"
#. Default: "Enable anonymous email field"
#: ../interfaces.py:350
msgid "label_anonymous_email_enabled"
msgstr ""
#. Default: "Apply"
#: ../browser/moderation.pt:71
msgid "label_apply"
msgstr "Toepassen"
#. Default: "Captcha"
#: ../interfaces.py:80
#: ../interfaces.py:286
msgid "label_captcha"
msgstr "Captcha"
#. Default: "Comment"
#: ../interfaces.py:275
#: ../interfaces.py:163
msgid "label_comment"
msgstr "Commentaar"
#. Default: "Commenting has been disabled."
#: ../browser/comments.pt:130
#: ../browser/comments.pt:163
msgid "label_commenting_disabled"
msgstr "Commentaar is uitgeschakeld"
@ -293,23 +382,33 @@ msgstr "Commentaar is uitgeschakeld"
msgid "label_delete"
msgstr "Verwijderen"
#. Default: "Enable deleting own comments"
#: ../interfaces.py:258
msgid "label_delete_own_comment_enabled"
msgstr ""
#. Default: "Enable editing of comments"
#: ../interfaces.py:247
msgid "label_edit_comment_enabled"
msgstr ""
#. Default: "Globally enable comments"
#: ../interfaces.py:24
#: ../interfaces.py:200
msgid "label_globally_enabled"
msgstr "Commentaar globaal toestaan"
#. Default: "Enable comment moderation"
#: ../interfaces.py:48
#: ../interfaces.py:228
msgid "label_moderation_enabled"
msgstr "Moderatie is ingeschakeld"
#. Default: "Moderator Email Address"
#: ../interfaces.py:117
#: ../interfaces.py:325
msgid "label_moderator_email"
msgstr "Moderator emailadres"
#. Default: "Enable moderator email notification"
#: ../interfaces.py:105
#: ../interfaces.py:313
msgid "label_moderator_notification_enabled"
msgstr "Notificatie voor moderator inschakelen"
@ -319,12 +418,12 @@ msgid "label_publish"
msgstr "Publiceren"
#. Default: "says:"
#: ../browser/comments.pt:74
#: ../browser/comments.pt:78
msgid "label_says"
msgstr "zegt:"
#. Default: "Show commenter image"
#: ../interfaces.py:95
#: ../interfaces.py:302
msgid "label_show_commenter_image"
msgstr "Toon portret commentator"
@ -334,27 +433,27 @@ msgid "label_show_full_comment_text"
msgstr "Toon het volledige commentaar"
#. Default: "Subject"
#: ../interfaces.py:271
#: ../interfaces.py:158
msgid "label_subject"
msgstr "Onderwerp"
#. Default: "Comment text transform"
#: ../interfaces.py:64
#: ../interfaces.py:269
msgid "label_text_transform"
msgstr "Reactie tekst transformatie"
#. Default: "Enable user email notification"
#: ../interfaces.py:125
#: ../interfaces.py:337
msgid "label_user_notification_enabled"
msgstr "Gebruikers-notificatie ingeschakeld"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n"
#: ../comment.py:50
#: ../comment.py:61
msgid "mail_notification_message"
msgstr "Een commentaar op '${title}' is geplaatst: ${link}"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n\nApprove comment:\n${link_approve}\n\nDelete comment:\n${link_delete}\n"
#: ../comment.py:58
#: ../comment.py:69
msgid "mail_notification_message_moderator"
msgstr "Commentaar op '${title}' is geplaatst: ${link}"

View File

@ -14,103 +14,127 @@ msgstr ""
"Preferred-Encodings: utf-8 latin1\n"
"Domain: plone.app.discussion\n"
#: ../comment.py:264
#: ../comment.py:359
msgid "A comment has been posted."
msgstr ""
#: ../interfaces.py:257
#: ../interfaces.py:144
msgid "A comment id unique to this conversation"
msgstr "En kommentar-id unik for denne kommentaren"
#: ../browser/comments.py:67
#: ../browser/comments.py:72
msgid "Add a comment"
msgstr "Legg til en kommentar"
#: ../browser/controlpanel.py:62
#: ../browser/controlpanel.py:75
msgid "Anonymous Comments"
msgstr "Anonym kommentar"
#: ../interfaces.py:282
msgid "Author name (for display)"
msgstr "Forfatternavn (synlig)"
#: ../browser/comments.py:248
#: ../browser/controlpanel.py:80
#: ../browser/comments.py:275
#: ../browser/controlpanel.py:93
msgid "Cancel"
msgstr "Avbryt"
#: ../browser/controlpanel.py:76
#: ../interfaces.py:184
msgid "Captcha"
msgstr ""
#: ../browser/controlpanel.py:89
msgid "Changes saved"
msgstr ""
#: ../browser/moderation.py:133
#: ../browser/moderation.py:186
msgid "Comment approved."
msgstr "Kommentaren er godkjent"
#: ../browser/moderation.py:94
#: ../contentrules.py:92
msgid "Comment author email"
msgstr ""
#: ../contentrules.py:81
msgid "Comment author full name"
msgstr ""
#: ../contentrules.py:70
msgid "Comment author user name"
msgstr ""
#: ../browser/moderation.py:111
msgid "Comment deleted."
msgstr "Kommentaren er slettet"
#: ../browser/controlpanel.py:63
#: ../contentrules.py:48
msgid "Comment id"
msgstr ""
#: ../contentrules.py:59
msgid "Comment text"
msgstr ""
#: ../browser/controlpanel.py:76
msgid "Commenter Image"
msgstr "Forfatterbilde"
msgid "Commenting infrastructure for Plone"
msgstr ""
#: ../interfaces.py:252
#: ../contentrules.py:47
msgid "Comments"
msgstr ""
#: ../interfaces.py:139
msgid "Conversation"
msgstr "Diskusjon"
#: ../interfaces.py:283
#: ../interfaces.py:177
msgid "Creation date"
msgstr "Dato opprettet"
#: ../interfaces.py:162
msgid "Date of the most recent comment"
msgstr "Dato for den nyeste kommentaren"
#: ../interfaces.py:41
msgid "Date of the most recent public comment"
msgstr ""
#: ../vocabularies.py:44
msgid "Disabled"
msgstr "Slått av"
#: ../browser/controlpanel.py:32
#: ../browser/controlpanel.py:33
msgid "Discussion settings"
msgstr "Innstillinger for kommentarer"
#: ../browser/controlpanel.py:82
#: ../browser/controlpanel.py:95
msgid "Edit cancelled"
msgstr ""
#: ../interfaces.py:269
#: ../interfaces.py:156
msgid "Email"
msgstr "E-post"
#: ../browser/controlpanel.py:61
#: ../browser/controlpanel.py:74
msgid "Enable Comments"
msgstr "Slå på kommentarer"
#: ../interfaces.py:260
#: ../interfaces.py:147
msgid "Id of comment this comment is in reply to"
msgstr "Id til kommentar som denne kommentaren er en kommentar til"
#: ../interfaces.py:274
#: ../interfaces.py:161
msgid "MIME type"
msgstr "MIME-type"
#: ../browser/controlpanel.py:65
#: ../browser/controlpanel.py:78
msgid "Moderator Email Notification"
msgstr "Varsling av moderator på epost"
#: ../interfaces.py:284
#: ../interfaces.py:178
msgid "Modification date"
msgstr "Endringsdato"
#: ../interfaces.py:254
#: ../interfaces.py:141
msgid "Name"
msgstr "Navn"
#: ../interfaces.py:278
#: ../interfaces.py:170
msgid "Notify me of new comments via email."
msgstr ""
@ -118,32 +142,44 @@ msgstr ""
msgid "Plone Discussions"
msgstr ""
#: ../interfaces.py:247
#: ../interfaces.py:134
msgid "Portal type"
msgstr "Portaltype"
#: ../browser/controlpanel.py:69
#: ../browser/controlpanel.py:82
msgid "Save"
msgstr ""
#: ../interfaces.py:167
#: ../interfaces.py:46
msgid "The set of unique commentators (usernames)"
msgstr "Listen over forfattere (brukernavn)"
#: ../interfaces.py:156
msgid "Total number of comments on this item"
msgstr "Antall kommentarer på denne artikkelen"
#: ../interfaces.py:51
msgid "The set of unique commentators (usernames) of published_comments"
msgstr ""
#: ../browser/controlpanel.py:67
#: ../interfaces.py:35
msgid "Total number of public comments on this item"
msgstr ""
#: ../comment.py:175
msgid "Transform '%s' => '%s' not available."
msgstr ""
#: ../browser/controlpanel.py:80
msgid "User Email Notification"
msgstr ""
#: ../browser/comments.py:241
#: ../interfaces.py:176
msgid "Username of the commenter"
msgstr ""
#: ../browser/comments.py:268
msgid "Your comment awaits moderator approval."
msgstr "Kommentaren venter på godkjenning av moderator."
#. Default: "Comment"
#: ../browser/comments.py:123
#: ../browser/comments.py:138
msgid "add_comment_button"
msgstr "Kommentér"
@ -157,26 +193,56 @@ msgstr "Slett"
msgid "bulkactions_publish"
msgstr "Godkjenn"
#. Default: "Cancel"
#: ../browser/comment.py:97
msgid "cancel_form_button"
msgstr ""
#. Default: "You can add a comment by filling out the form below. Plain text formatting. Web and email addresses are transformed into clickable links."
#: ../browser/comments.py:52
#: ../browser/comments.py:57
msgid "comment_description_intelligent_text"
msgstr ""
#. Default: "You can add a comment by filling out the form below. Plain text formatting. You can use the Markdown syntax for links and images."
#: ../browser/comments.py:51
msgid "comment_description_markdown"
msgstr ""
#. Default: "Comments are moderated."
#: ../browser/comments.py:58
#: ../browser/comments.py:63
msgid "comment_description_moderation_enabled"
msgstr ""
#. Default: "You can add a comment by filling out the form below. Plain text formatting."
#: ../browser/comments.py:47
#: ../browser/comments.py:46
msgid "comment_description_plain_text"
msgstr ""
#. Default: "${creator} on ${content}"
#: ../comment.py:46
#. Default: "Edit comment cancelled"
#: ../browser/comment.py:101
msgid "comment_edit_cancel_notification"
msgstr ""
#. Default: "Comment was edited"
#: ../browser/comment.py:91
msgid "comment_edit_notification"
msgstr ""
#. Default: "${author_name} on ${content}"
#: ../comment.py:57
msgid "comment_title"
msgstr ""
#. Default: "Edit comment"
#: ../browser/comment.py:70
msgid "edit_comment_form_button"
msgstr ""
#. Default: "Edit comment"
#: ../browser/comment.py:54
msgid "edit_comment_form_title"
msgstr ""
#. Default: "Action"
#: ../browser/moderation.pt:85
msgid "heading_action"
@ -208,88 +274,109 @@ msgid "heading_moderate_comments"
msgstr "Moderer kommentar"
#. Default: "If selected, anonymous users are able to post comments without loggin in. It is highly recommended to use a captcha solution to prevent spam if this setting is enabled."
#: ../interfaces.py:38
#: ../interfaces.py:216
msgid "help_anonymous_comments"
msgstr "Dersom innstillingen er valgt kan anonyme brukere kommentere uten å logge inn. Det er anbefalt å bruke en captcha-løsning for å forhindre nettsøppel dersom denne innstillingen er valgt"
#. Default: "If selected, anonymous user will have to give their email."
#: ../interfaces.py:352
msgid "help_anonymous_email_enabled"
msgstr ""
#. Default: "Use this setting to enable or disable Captcha validation for comments. Install plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet, or collective.z3cform.norobots if there are no options available."
#: ../interfaces.py:82
#: ../interfaces.py:288
#, fuzzy
msgid "help_captcha"
msgstr "Bruk denne innstillingen for å aktivere eller deaktivere captcha-validering av kommentarer. Installér plone.formwidget.captcha eller plone.formwidget.recaptcha dersom det mangler valg her."
#. Default: "If selected, supports deleting of own comments for users with the 'Delete own comments' permission."
#: ../interfaces.py:260
msgid "help_delete_own_comment_enabled"
msgstr ""
#. Default: "Some discussion related settings are not located in the Discussion Control Panel.\nTo enable comments for a specific content type, go to the Types Control Panel of this type and choose \"Allow comments\".\nTo enable the moderation workflow for comments, go to the Types Control Panel, choose \"Comment\" and set workflow to \"Comment Review Workflow\"."
#: ../browser/controlpanel.py:33
#: ../browser/controlpanel.py:34
#, fuzzy
msgid "help_discussion_settings_editform"
msgstr ""
"Noen innstillinger for kommentarer finnes utenfor kontrollpanelet for kommentarer. For å aktivere kommentarer for en spesifíkk innholdstype må man gå til kontrollpanelet for denne innholdstypen og velge 'aktiver moderering'.\n"
"For å aktivere arbeidsflyten for moderering, må man gå til kontrollpanelet for innholdstyper og velge \"Kommentarer\" og stille inn arbeidsflyten til å vere \"Comment Review Workflow\"."
#. Default: "If selected, supports editing of comments for users with the 'Edit comments' permission."
#: ../interfaces.py:249
msgid "help_edit_comment_enabled"
msgstr ""
#. Default: "If selected, users are able to post comments on the site. Though, you have to enable comments for specific content types, folders or content objects before users will be able to post comments."
#: ../interfaces.py:26
#: ../interfaces.py:202
#, fuzzy
msgid "help_globally_enabled"
msgstr "Dersom denne instillingen er valgt kan brukerene legge til kommentarer på nettstedet. Men du må likevel aktivere kommentarer for spesifikke innholdstyper, mapper eller innholdsobjekter før brukerene får lov til å legge til kommentarer."
#. Default: "If selected, comments will enter a 'Pending' state in which they are invisible to the public. A user with the 'Review comments' permission ('Reviewer' or 'Manager') can approve comments to make them visible to the public. If you want to enable a custom comment workflow, you have to go to the types control panel."
#: ../interfaces.py:50
#: ../interfaces.py:232
msgid "help_moderation_enabled"
msgstr ""
#. Default: "Address to which moderator notifications will be sent."
#: ../interfaces.py:118
#: ../interfaces.py:329
msgid "help_moderator_email"
msgstr ""
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be found in the 'Mail settings' control panel (Site 'From' address)"
#: ../interfaces.py:107
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be set below."
#: ../interfaces.py:315
#, fuzzy
msgid "help_moderator_notification_enabled"
msgstr "Dersom innstillingen er valgt vil moderatoren bli varslet når en kommentar er lagt til."
#. Default: "If selected, an image of the user is shown next to the comment."
#: ../interfaces.py:97
#: ../interfaces.py:304
msgid "help_show_commenter_image"
msgstr "Dersom denne er valgt vil bildet av brukeren vise ved siden av kommentaren."
#. Default: "Use this setting to choose if the comment text should be transformed in any way. You can choose between 'Plain text' and 'Intelligent text'. 'Intelligent text' converts plain text into HTML where line breaks and indentation is preserved, and web and email addresses are made into clickable links."
#: ../interfaces.py:66
#: ../interfaces.py:271
msgid "help_text_transform"
msgstr ""
#. Default: "If selected, users can choose to be notified of new comments by email."
#: ../interfaces.py:127
#: ../interfaces.py:341
msgid "help_user_notification_enabled"
msgstr ""
#. Default: "Anonymous"
#: ../comment.py:156
#: ../browser/comments.pt:75
#: ../comment.py:193
msgid "label_anonymous"
msgstr ""
#. Default: "Enable anonymous comments"
#: ../interfaces.py:36
#: ../interfaces.py:214
msgid "label_anonymous_comments"
msgstr ""
#. Default: "Enable anonymous email field"
#: ../interfaces.py:350
msgid "label_anonymous_email_enabled"
msgstr ""
#. Default: "Apply"
#: ../browser/moderation.pt:71
msgid "label_apply"
msgstr "Bruk"
#. Default: "Captcha"
#: ../interfaces.py:80
#: ../interfaces.py:286
msgid "label_captcha"
msgstr ""
#. Default: "Comment"
#: ../interfaces.py:275
#: ../interfaces.py:163
msgid "label_comment"
msgstr ""
#. Default: "Commenting has been disabled."
#: ../browser/comments.pt:130
#: ../browser/comments.pt:163
msgid "label_commenting_disabled"
msgstr ""
@ -298,23 +385,33 @@ msgstr ""
msgid "label_delete"
msgstr "Slett"
#. Default: "Enable deleting own comments"
#: ../interfaces.py:258
msgid "label_delete_own_comment_enabled"
msgstr ""
#. Default: "Enable editing of comments"
#: ../interfaces.py:247
msgid "label_edit_comment_enabled"
msgstr ""
#. Default: "Globally enable comments"
#: ../interfaces.py:24
#: ../interfaces.py:200
msgid "label_globally_enabled"
msgstr "Aktiver kommentarer globalt"
#. Default: "Enable comment moderation"
#: ../interfaces.py:48
#: ../interfaces.py:228
msgid "label_moderation_enabled"
msgstr ""
#. Default: "Moderator Email Address"
#: ../interfaces.py:117
#: ../interfaces.py:325
msgid "label_moderator_email"
msgstr ""
#. Default: "Enable moderator email notification"
#: ../interfaces.py:105
#: ../interfaces.py:313
msgid "label_moderator_notification_enabled"
msgstr "Slå på e-postvarsling av moderator"
@ -324,12 +421,12 @@ msgid "label_publish"
msgstr "Godkjenn"
#. Default: "says:"
#: ../browser/comments.pt:74
#: ../browser/comments.pt:78
msgid "label_says"
msgstr ""
#. Default: "Show commenter image"
#: ../interfaces.py:95
#: ../interfaces.py:302
msgid "label_show_commenter_image"
msgstr ""
@ -339,27 +436,27 @@ msgid "label_show_full_comment_text"
msgstr "Vis hele kommentaren"
#. Default: "Subject"
#: ../interfaces.py:271
#: ../interfaces.py:158
msgid "label_subject"
msgstr ""
#. Default: "Comment text transform"
#: ../interfaces.py:64
#: ../interfaces.py:269
msgid "label_text_transform"
msgstr ""
#. Default: "Enable user email notification"
#: ../interfaces.py:125
#: ../interfaces.py:337
msgid "label_user_notification_enabled"
msgstr ""
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n"
#: ../comment.py:50
#: ../comment.py:61
msgid "mail_notification_message"
msgstr ""
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n\nApprove comment:\n${link_approve}\n\nDelete comment:\n${link_delete}\n"
#: ../comment.py:58
#: ../comment.py:69
msgid "mail_notification_message_moderator"
msgstr ""

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: plone.app.discussion\n"
"POT-Creation-Date: 2011-04-22 17:12+0000\n"
"POT-Creation-Date: 2015-03-23 08:03+0000\n"
"PO-Revision-Date: 2010-01-28 15:00+0000\n"
"Last-Translator: Hanno Schlichting <hannosch@plone.org>\n"
"Language-Team: Hanno Schlichting <hannosch@plone.org>\n"
@ -14,107 +14,131 @@ msgstr ""
"Preferred-Encodings: utf-8 latin1\n"
"Domain: DOMAIN\n"
#: ../browser/comments.py:90
#: ../browser/comments.py:95
msgid ""
msgstr ""
#: ../comment.py:264
#: ../comment.py:359
msgid "A comment has been posted."
msgstr ""
#: ../interfaces.py:257
#: ../interfaces.py:144
msgid "A comment id unique to this conversation"
msgstr ""
#: ../browser/comments.py:67
#: ../browser/comments.py:72
msgid "Add a comment"
msgstr ""
#: ../browser/controlpanel.py:62
#: ../browser/controlpanel.py:75
msgid "Anonymous Comments"
msgstr ""
#: ../interfaces.py:282
msgid "Author name (for display)"
msgstr ""
#: ../browser/comments.py:248
#: ../browser/controlpanel.py:80
#: ../browser/comments.py:275
#: ../browser/controlpanel.py:93
msgid "Cancel"
msgstr ""
#: ../browser/controlpanel.py:76
#: ../interfaces.py:184
msgid "Captcha"
msgstr ""
#: ../browser/controlpanel.py:89
msgid "Changes saved"
msgstr ""
#: ../browser/moderation.py:133
#: ../browser/moderation.py:186
msgid "Comment approved."
msgstr ""
#: ../browser/moderation.py:94
#: ../contentrules.py:92
msgid "Comment author email"
msgstr ""
#: ../contentrules.py:81
msgid "Comment author full name"
msgstr ""
#: ../contentrules.py:70
msgid "Comment author user name"
msgstr ""
#: ../browser/moderation.py:111
msgid "Comment deleted."
msgstr ""
#: ../browser/controlpanel.py:63
#: ../contentrules.py:48
msgid "Comment id"
msgstr ""
#: ../contentrules.py:59
msgid "Comment text"
msgstr ""
#: ../browser/controlpanel.py:76
msgid "Commenter Image"
msgstr ""
msgid "Commenting infrastructure for Plone"
msgstr ""
#: ../interfaces.py:252
#: ../contentrules.py:47
msgid "Comments"
msgstr ""
#: ../interfaces.py:139
msgid "Conversation"
msgstr ""
#: ../interfaces.py:283
#: ../interfaces.py:177
msgid "Creation date"
msgstr ""
#: ../interfaces.py:162
msgid "Date of the most recent comment"
#: ../interfaces.py:41
msgid "Date of the most recent public comment"
msgstr ""
#: ../vocabularies.py:44
msgid "Disabled"
msgstr ""
#: ../browser/controlpanel.py:32
#: ../browser/controlpanel.py:33
msgid "Discussion settings"
msgstr ""
#: ../browser/controlpanel.py:82
#: ../browser/controlpanel.py:95
msgid "Edit cancelled"
msgstr ""
#: ../interfaces.py:269
#: ../interfaces.py:156
msgid "Email"
msgstr ""
#: ../browser/controlpanel.py:61
#: ../browser/controlpanel.py:74
msgid "Enable Comments"
msgstr ""
#: ../interfaces.py:260
#: ../interfaces.py:147
msgid "Id of comment this comment is in reply to"
msgstr ""
#: ../interfaces.py:274
#: ../interfaces.py:161
msgid "MIME type"
msgstr ""
#: ../browser/controlpanel.py:65
#: ../browser/controlpanel.py:78
msgid "Moderator Email Notification"
msgstr ""
#: ../interfaces.py:284
#: ../interfaces.py:178
msgid "Modification date"
msgstr ""
#: ../interfaces.py:254
#: ../interfaces.py:141
msgid "Name"
msgstr ""
#: ../interfaces.py:278
#: ../interfaces.py:170
msgid "Notify me of new comments via email."
msgstr ""
@ -122,32 +146,44 @@ msgstr ""
msgid "Plone Discussions"
msgstr ""
#: ../interfaces.py:247
#: ../interfaces.py:134
msgid "Portal type"
msgstr ""
#: ../browser/controlpanel.py:69
#: ../browser/controlpanel.py:82
msgid "Save"
msgstr ""
#: ../interfaces.py:167
#: ../interfaces.py:46
msgid "The set of unique commentators (usernames)"
msgstr ""
#: ../interfaces.py:156
msgid "Total number of comments on this item"
#: ../interfaces.py:51
msgid "The set of unique commentators (usernames) of published_comments"
msgstr ""
#: ../browser/controlpanel.py:67
#: ../interfaces.py:35
msgid "Total number of public comments on this item"
msgstr ""
#: ../comment.py:175
msgid "Transform '%s' => '%s' not available."
msgstr ""
#: ../browser/controlpanel.py:80
msgid "User Email Notification"
msgstr ""
#: ../browser/comments.py:241
#: ../interfaces.py:176
msgid "Username of the commenter"
msgstr ""
#: ../browser/comments.py:268
msgid "Your comment awaits moderator approval."
msgstr ""
#. Default: "Comment"
#: ../browser/comments.py:123
#: ../browser/comments.py:138
msgid "add_comment_button"
msgstr ""
@ -161,26 +197,56 @@ msgstr ""
msgid "bulkactions_publish"
msgstr ""
#. Default: "Cancel"
#: ../browser/comment.py:97
msgid "cancel_form_button"
msgstr ""
#. Default: "You can add a comment by filling out the form below. Plain text formatting. Web and email addresses are transformed into clickable links."
#: ../browser/comments.py:52
#: ../browser/comments.py:57
msgid "comment_description_intelligent_text"
msgstr ""
#. Default: "You can add a comment by filling out the form below. Plain text formatting. You can use the Markdown syntax for links and images."
#: ../browser/comments.py:51
msgid "comment_description_markdown"
msgstr ""
#. Default: "Comments are moderated."
#: ../browser/comments.py:58
#: ../browser/comments.py:63
msgid "comment_description_moderation_enabled"
msgstr ""
#. Default: "You can add a comment by filling out the form below. Plain text formatting."
#: ../browser/comments.py:47
#: ../browser/comments.py:46
msgid "comment_description_plain_text"
msgstr ""
#. Default: "${creator} on ${content}"
#: ../comment.py:46
#. Default: "Edit comment cancelled"
#: ../browser/comment.py:101
msgid "comment_edit_cancel_notification"
msgstr ""
#. Default: "Comment was edited"
#: ../browser/comment.py:91
msgid "comment_edit_notification"
msgstr ""
#. Default: "${author_name} on ${content}"
#: ../comment.py:57
msgid "comment_title"
msgstr ""
#. Default: "Edit comment"
#: ../browser/comment.py:70
msgid "edit_comment_form_button"
msgstr ""
#. Default: "Edit comment"
#: ../browser/comment.py:54
msgid "edit_comment_form_title"
msgstr ""
#. Default: "Action"
#: ../browser/moderation.pt:85
msgid "heading_action"
@ -212,82 +278,103 @@ msgid "heading_moderate_comments"
msgstr ""
#. Default: "If selected, anonymous users are able to post comments without loggin in. It is highly recommended to use a captcha solution to prevent spam if this setting is enabled."
#: ../interfaces.py:38
#: ../interfaces.py:216
msgid "help_anonymous_comments"
msgstr ""
#. Default: "If selected, anonymous user will have to give their email."
#: ../interfaces.py:352
msgid "help_anonymous_email_enabled"
msgstr ""
#. Default: "Use this setting to enable or disable Captcha validation for comments. Install plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet, or collective.z3cform.norobots if there are no options available."
#: ../interfaces.py:82
#: ../interfaces.py:288
msgid "help_captcha"
msgstr ""
#. Default: "If selected, supports deleting of own comments for users with the 'Delete own comments' permission."
#: ../interfaces.py:260
msgid "help_delete_own_comment_enabled"
msgstr ""
#. Default: "Some discussion related settings are not located in the Discussion Control Panel.\nTo enable comments for a specific content type, go to the Types Control Panel of this type and choose \"Allow comments\".\nTo enable the moderation workflow for comments, go to the Types Control Panel, choose \"Comment\" and set workflow to \"Comment Review Workflow\"."
#: ../browser/controlpanel.py:33
#: ../browser/controlpanel.py:34
msgid "help_discussion_settings_editform"
msgstr ""
#. Default: "If selected, users are able to post comments on the site. However, you must enable comments for specific content types, folders or content objects before users will be able to post comments."
#: ../interfaces.py:26
#. Default: "If selected, supports editing of comments for users with the 'Edit comments' permission."
#: ../interfaces.py:249
msgid "help_edit_comment_enabled"
msgstr ""
#. Default: "If selected, users are able to post comments on the site. Though, you have to enable comments for specific content types, folders or content objects before users will be able to post comments."
#: ../interfaces.py:202
msgid "help_globally_enabled"
msgstr ""
#. Default: "If selected, comments will enter a 'Pending' state in which they are invisible to the public. A user with the 'Review comments' permission ('Reviewer' or 'Manager') can approve comments to make them visible to the public. If you want to enable a custom comment workflow, you have to go to the types control panel."
#: ../interfaces.py:50
#: ../interfaces.py:232
msgid "help_moderation_enabled"
msgstr ""
#. Default: "Address to which moderator notifications will be sent."
#: ../interfaces.py:118
#: ../interfaces.py:329
msgid "help_moderator_email"
msgstr ""
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be found in the 'Mail settings' control panel (Site 'From' address)"
#: ../interfaces.py:107
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be set below."
#: ../interfaces.py:315
msgid "help_moderator_notification_enabled"
msgstr ""
#. Default: "If selected, an image of the user is shown next to the comment."
#: ../interfaces.py:97
#: ../interfaces.py:304
msgid "help_show_commenter_image"
msgstr ""
#. Default: "Use this setting to choose if the comment text should be transformed in any way. You can choose between 'Plain text' and 'Intelligent text'. 'Intelligent text' converts plain text into HTML where line breaks and indentation is preserved, and web and email addresses are made into clickable links."
#: ../interfaces.py:66
#: ../interfaces.py:271
msgid "help_text_transform"
msgstr ""
#. Default: "If selected, users can choose to be notified of new comments by email."
#: ../interfaces.py:127
#: ../interfaces.py:341
msgid "help_user_notification_enabled"
msgstr ""
#. Default: "Anonymous"
#: ../comment.py:156
#: ../browser/comments.pt:75
#: ../comment.py:193
msgid "label_anonymous"
msgstr ""
#. Default: "Enable anonymous comments"
#: ../interfaces.py:36
#: ../interfaces.py:214
msgid "label_anonymous_comments"
msgstr ""
#. Default: "Enable anonymous email field"
#: ../interfaces.py:350
msgid "label_anonymous_email_enabled"
msgstr ""
#. Default: "Apply"
#: ../browser/moderation.pt:71
msgid "label_apply"
msgstr ""
#. Default: "Captcha"
#: ../interfaces.py:80
#: ../interfaces.py:286
msgid "label_captcha"
msgstr ""
#. Default: "Comment"
#: ../interfaces.py:275
#: ../interfaces.py:163
msgid "label_comment"
msgstr ""
#. Default: "Commenting has been disabled."
#: ../browser/comments.pt:130
#: ../browser/comments.pt:163
msgid "label_commenting_disabled"
msgstr ""
@ -296,23 +383,33 @@ msgstr ""
msgid "label_delete"
msgstr ""
#. Default: "Enable deleting own comments"
#: ../interfaces.py:258
msgid "label_delete_own_comment_enabled"
msgstr ""
#. Default: "Enable editing of comments"
#: ../interfaces.py:247
msgid "label_edit_comment_enabled"
msgstr ""
#. Default: "Globally enable comments"
#: ../interfaces.py:24
#: ../interfaces.py:200
msgid "label_globally_enabled"
msgstr ""
#. Default: "Enable comment moderation"
#: ../interfaces.py:48
#: ../interfaces.py:228
msgid "label_moderation_enabled"
msgstr ""
#. Default: "Moderator Email Address"
#: ../interfaces.py:117
#: ../interfaces.py:325
msgid "label_moderator_email"
msgstr ""
#. Default: "Enable moderator email notification"
#: ../interfaces.py:105
#: ../interfaces.py:313
msgid "label_moderator_notification_enabled"
msgstr ""
@ -322,12 +419,12 @@ msgid "label_publish"
msgstr ""
#. Default: "says:"
#: ../browser/comments.pt:74
#: ../browser/comments.pt:78
msgid "label_says"
msgstr ""
#. Default: "Show commenter image"
#: ../interfaces.py:95
#: ../interfaces.py:302
msgid "label_show_commenter_image"
msgstr ""
@ -337,27 +434,27 @@ msgid "label_show_full_comment_text"
msgstr ""
#. Default: "Subject"
#: ../interfaces.py:271
#: ../interfaces.py:158
msgid "label_subject"
msgstr ""
#. Default: "Comment text transform"
#: ../interfaces.py:64
#: ../interfaces.py:269
msgid "label_text_transform"
msgstr ""
#. Default: "Enable user email notification"
#: ../interfaces.py:125
#: ../interfaces.py:337
msgid "label_user_notification_enabled"
msgstr ""
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n"
#: ../comment.py:50
#: ../comment.py:61
msgid "mail_notification_message"
msgstr ""
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n\nApprove comment:\n${link_approve}\n\nDelete comment:\n${link_delete}\n"
#: ../comment.py:58
#: ../comment.py:69
msgid "mail_notification_message_moderator"
msgstr ""

View File

@ -0,0 +1,494 @@
msgid ""
msgstr ""
"Project-Id-Version: plone.app.discussion\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI +ZONE\n"
"PO-Revision-Date: 2011-04-14 17:20-0300\n"
"Last-Translator: Rui Dinis Silva <rds@eurotux.com>\n"
"Language-Team: Eurotux <dev@eurotux.com>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0\n"
"Language-Code: pt\n"
"Language-Name: Portuguese\n"
"Preferred-Encodings: utf-8 latin1\n"
"Domain: plone.app.discussion\n"
"X-Poedit-Language: Português\n"
#: ../comment.py:359
msgid "A comment has been posted."
msgstr "Foi adicionado um comentário."
#: ../interfaces.py:144
msgid "A comment id unique to this conversation"
msgstr "Um id do comentário único para esta conversação."
#: ../browser/comments.py:72
msgid "Add a comment"
msgstr "Adicionar comentário"
#: ../browser/controlpanel.py:75
msgid "Anonymous Comments"
msgstr "Comentários Anónimos"
#: ../browser/comments.py:275
#: ../browser/controlpanel.py:93
msgid "Cancel"
msgstr "Cancelar"
#: ../interfaces.py:184
msgid "Captcha"
msgstr ""
#: ../browser/controlpanel.py:89
msgid "Changes saved"
msgstr "Alterações guardadas"
#: ../browser/moderation.py:186
msgid "Comment approved."
msgstr "Comentário aprovado"
#: ../contentrules.py:92
msgid "Comment author email"
msgstr ""
#: ../contentrules.py:81
msgid "Comment author full name"
msgstr ""
#: ../contentrules.py:70
msgid "Comment author user name"
msgstr ""
#: ../browser/moderation.py:111
msgid "Comment deleted."
msgstr "Comentário excluído."
#: ../contentrules.py:48
msgid "Comment id"
msgstr ""
#: ../contentrules.py:59
msgid "Comment text"
msgstr ""
#: ../browser/controlpanel.py:76
msgid "Commenter Image"
msgstr "Imagem do comentador"
msgid "Commenting infrastructure for Plone"
msgstr "Infraestrutura de comentários para o Plone"
#: ../contentrules.py:47
msgid "Comments"
msgstr ""
#: ../interfaces.py:139
msgid "Conversation"
msgstr "Conversação"
#: ../interfaces.py:177
msgid "Creation date"
msgstr "Data de criação"
#: ../interfaces.py:41
msgid "Date of the most recent public comment"
msgstr ""
#: ../vocabularies.py:44
msgid "Disabled"
msgstr "Desativado"
#: ../browser/controlpanel.py:33
msgid "Discussion settings"
msgstr "Configurações da discussão"
#: ../browser/controlpanel.py:95
msgid "Edit cancelled"
msgstr "Edição cancelada"
#: ../interfaces.py:156
msgid "Email"
msgstr "Email"
#: ../browser/controlpanel.py:74
msgid "Enable Comments"
msgstr "Permitir comentários"
#: ../interfaces.py:147
msgid "Id of comment this comment is in reply to"
msgstr "ID do comentário para qual este comentário é resposta"
#: ../interfaces.py:161
msgid "MIME type"
msgstr "MIME type"
#: ../browser/controlpanel.py:78
msgid "Moderator Email Notification"
msgstr "Notificação de e-mail para o moderador"
#: ../interfaces.py:178
msgid "Modification date"
msgstr "Data de modificação"
#: ../interfaces.py:141
msgid "Name"
msgstr "Nome"
#: ../interfaces.py:170
msgid "Notify me of new comments via email."
msgstr "Notificar-me por email da existência de novos comentários."
#: ./plone.app.discussion/plone/app/discussion/configure.zcml
msgid "Plone Discussions"
msgstr "Discussões Plone"
#: ../interfaces.py:134
msgid "Portal type"
msgstr "Tipo de conteúdo"
#: ../browser/controlpanel.py:82
msgid "Save"
msgstr "Guardar"
#: ../interfaces.py:46
msgid "The set of unique commentators (usernames)"
msgstr "Lista de utilizadores que fizeram comentários (nome de utilizador)"
#: ../interfaces.py:51
msgid "The set of unique commentators (usernames) of published_comments"
msgstr ""
#: ../interfaces.py:35
msgid "Total number of public comments on this item"
msgstr ""
#: ../comment.py:175
msgid "Transform '%s' => '%s' not available."
msgstr ""
#: ../browser/controlpanel.py:80
msgid "User Email Notification"
msgstr "Notificar o utilizador por email"
#: ../interfaces.py:176
msgid "Username of the commenter"
msgstr ""
#: ../browser/comments.py:268
msgid "Your comment awaits moderator approval."
msgstr "Seu comentário encontra-se pendente e aguarda a aprovação do moderador."
#. Default: "Comment"
#: ../browser/comments.py:138
msgid "add_comment_button"
msgstr "Comentar"
#. Default: "Delete"
#: ../browser/moderation.pt:68
msgid "bulkactions_delete"
msgstr "Excluir"
#. Default: "Approve"
#: ../browser/moderation.pt:65
msgid "bulkactions_publish"
msgstr "Publicar"
#. Default: "Cancel"
#: ../browser/comment.py:97
msgid "cancel_form_button"
msgstr ""
#. Default: "You can add a comment by filling out the form below. Plain text formatting. Web and email addresses are transformed into clickable links."
#: ../browser/comments.py:57
msgid "comment_description_intelligent_text"
msgstr "Pode adicionar um comentário usando o formulário a seguir. Campo de texto simples. Endereços web e e-mail são transformados em links clicáveis."
#. Default: "You can add a comment by filling out the form below. Plain text formatting. You can use the Markdown syntax for links and images."
#: ../browser/comments.py:51
msgid "comment_description_markdown"
msgstr ""
#. Default: "Comments are moderated."
#: ../browser/comments.py:63
msgid "comment_description_moderation_enabled"
msgstr "Os comentários são moderados"
#. Default: "You can add a comment by filling out the form below. Plain text formatting."
#: ../browser/comments.py:46
msgid "comment_description_plain_text"
msgstr "Pode adicionar um comentário usando o formulário a seguir. Campo de texto simples."
#. Default: "Edit comment cancelled"
#: ../browser/comment.py:101
msgid "comment_edit_cancel_notification"
msgstr ""
#. Default: "Comment was edited"
#: ../browser/comment.py:91
msgid "comment_edit_notification"
msgstr ""
#. Default: "${author_name} on ${content}"
#: ../comment.py:57
#, fuzzy
msgid "comment_title"
msgstr "${creator} em ${content}"
#. Default: "Edit comment"
#: ../browser/comment.py:70
msgid "edit_comment_form_button"
msgstr ""
#. Default: "Edit comment"
#: ../browser/comment.py:54
msgid "edit_comment_form_title"
msgstr ""
#. Default: "Action"
#: ../browser/moderation.pt:85
msgid "heading_action"
msgstr "Acção"
#. Default: "Comment"
#: ../browser/moderation.pt:84
msgid "heading_comment"
msgstr "Comentário"
#. Default: "Commenter"
#: ../browser/moderation.pt:81
msgid "heading_commenter"
msgstr "Autor"
#. Default: "Date"
#: ../browser/moderation.pt:82
msgid "heading_date"
msgstr "Data"
#. Default: "In Response To"
#: ../browser/moderation.pt:83
msgid "heading_in_reponse_to"
msgstr "Em resposta a"
#. Default: "Moderate comments"
#: ../browser/moderation.pt:24
msgid "heading_moderate_comments"
msgstr "Moderar comentários"
#. Default: "If selected, anonymous users are able to post comments without loggin in. It is highly recommended to use a captcha solution to prevent spam if this setting is enabled."
#: ../interfaces.py:216
msgid "help_anonymous_comments"
msgstr "Se selecionado, os utilizadores anonimos poderão adicionar comentários sem estar autenticados. É altamente recomendável a utilização de uma solução de captcha para evitar spam quando esta configuração está activa."
#. Default: "If selected, anonymous user will have to give their email."
#: ../interfaces.py:352
msgid "help_anonymous_email_enabled"
msgstr ""
#. Default: "Use this setting to enable or disable Captcha validation for comments. Install plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet, or collective.z3cform.norobots if there are no options available."
#: ../interfaces.py:288
msgid "help_captcha"
msgstr "Utilize esta opção para ativar ou desativar o Captcha para os comentários. Instale plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet ou collective.z3cform.norobots caso não tenha nenhuma opção disponível."
#. Default: "If selected, supports deleting of own comments for users with the 'Delete own comments' permission."
#: ../interfaces.py:260
msgid "help_delete_own_comment_enabled"
msgstr ""
#. Default: "Some discussion related settings are not located in the Discussion Control Panel.\nTo enable comments for a specific content type, go to the Types Control Panel of this type and choose \"Allow comments\".\nTo enable the moderation workflow for comments, go to the Types Control Panel, choose \"Comment\" and set workflow to \"Comment Review Workflow\"."
#: ../browser/controlpanel.py:34
msgid "help_discussion_settings_editform"
msgstr ""
"Algumas configurações relacionadas com os comentários não se encontram localizadas no Painel de Controle de Comentários.\n"
"Para activar os comentários para um tipo de item específico, aceda à configuração de Tipos no Painel de Controle, encontre o tipo desejado e selecione \"Permitir comentários \".\n"
"Para ativar o workflow de moderação de comentários, aceda à configuração de Tipos no Painel de Controle, escolha \"Comentário\" e selecione o workflow para \"Workflow de Revisão de Comentários\"."
#. Default: "If selected, supports editing of comments for users with the 'Edit comments' permission."
#: ../interfaces.py:249
msgid "help_edit_comment_enabled"
msgstr ""
#. Default: "If selected, users are able to post comments on the site. Though, you have to enable comments for specific content types, folders or content objects before users will be able to post comments."
#: ../interfaces.py:202
msgid "help_globally_enabled"
msgstr "Se selecionado, permite que os visitantes adicionem comentários ao site. Porém, você deve habilitar comentários para cada tipo de conteúdo antes que os usuários possam adicionar comentários."
#. Default: "If selected, comments will enter a 'Pending' state in which they are invisible to the public. A user with the 'Review comments' permission ('Reviewer' or 'Manager') can approve comments to make them visible to the public. If you want to enable a custom comment workflow, you have to go to the types control panel."
#: ../interfaces.py:232
msgid "help_moderation_enabled"
msgstr "Se selecionado, os comentários serão adicionados no estado \"Pendente\", que é invisível ao público. Utilizadores com permissão para 'Moderar Comentários' ('Gestor' ou 'Administrador') podem aprovar os comentários para torná-los visíveis ao público. Caso queira ativar um workflow de comentários personalizado, aceda à Configuração dos Tipos no Painel de Controle."
#. Default: "Address to which moderator notifications will be sent."
#: ../interfaces.py:329
msgid "help_moderator_email"
msgstr "Endereço para o qual as notificações do moderador serão enviadas."
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be set below."
#: ../interfaces.py:315
#, fuzzy
msgid "help_moderator_notification_enabled"
msgstr "Se selecionado, o moderador será avisado quando um comentário precisar de atenção. O endereço de e-mail do moderador pode ser encontrado nas configurações de e-mail no Painel de Controle (campo Endereço de 'Remetente' do site)"
#. Default: "If selected, an image of the user is shown next to the comment."
#: ../interfaces.py:304
msgid "help_show_commenter_image"
msgstr "Se selecionado, uma imagem do usuário será exibida próxima ao comentário."
#. Default: "Use this setting to choose if the comment text should be transformed in any way. You can choose between 'Plain text' and 'Intelligent text'. 'Intelligent text' converts plain text into HTML where line breaks and indentation is preserved, and web and email addresses are made into clickable links."
#: ../interfaces.py:271
msgid "help_text_transform"
msgstr "Use esta configuração para escolher se o texto do comentário deve ser transformado. Você pode escolher entre 'texto puro' e 'texto inteligente'. 'Texto inteligente' converte texto simples em HTML, onde as quebras de linha e os recuos são preservados, e os endereços web e e-mail são transformados em links clicáveis."
#. Default: "If selected, users can choose to be notified of new comments by email."
#: ../interfaces.py:341
msgid "help_user_notification_enabled"
msgstr "Se selecionado, permite aos usuários solicitar o notificações por e-mail sempre que hover um novo comentário."
#. Default: "Anonymous"
#: ../browser/comments.pt:75
#: ../comment.py:193
msgid "label_anonymous"
msgstr "Anónimo"
#. Default: "Enable anonymous comments"
#: ../interfaces.py:214
msgid "label_anonymous_comments"
msgstr "Permitir comentários anónimos."
#. Default: "Enable anonymous email field"
#: ../interfaces.py:350
msgid "label_anonymous_email_enabled"
msgstr ""
#. Default: "Apply"
#: ../browser/moderation.pt:71
msgid "label_apply"
msgstr "Aplicar"
#. Default: "Captcha"
#: ../interfaces.py:286
msgid "label_captcha"
msgstr "Captcha"
#. Default: "Comment"
#: ../interfaces.py:163
msgid "label_comment"
msgstr "Comentário"
#. Default: "Commenting has been disabled."
#: ../browser/comments.pt:163
msgid "label_commenting_disabled"
msgstr "Os comentários foram desativados."
#. Default: "Delete"
#: ../browser/moderation.pt:130
msgid "label_delete"
msgstr "Excluir"
#. Default: "Enable deleting own comments"
#: ../interfaces.py:258
msgid "label_delete_own_comment_enabled"
msgstr ""
#. Default: "Enable editing of comments"
#: ../interfaces.py:247
msgid "label_edit_comment_enabled"
msgstr ""
#. Default: "Globally enable comments"
#: ../interfaces.py:200
msgid "label_globally_enabled"
msgstr "Ativar comentários globalmente"
#. Default: "Enable comment moderation"
#: ../interfaces.py:228
msgid "label_moderation_enabled"
msgstr "Ativar moderação de comentários"
#. Default: "Moderator Email Address"
#: ../interfaces.py:325
msgid "label_moderator_email"
msgstr "Endereço de e-mail do moderador"
#. Default: "Enable moderator email notification"
#: ../interfaces.py:313
msgid "label_moderator_notification_enabled"
msgstr "Ativar notificação ao moderador"
#. Default: "Approve"
#: ../browser/moderation.pt:121
msgid "label_publish"
msgstr "Aprovar"
#. Default: "says:"
#: ../browser/comments.pt:78
msgid "label_says"
msgstr "disse:"
#. Default: "Show commenter image"
#: ../interfaces.py:302
msgid "label_show_commenter_image"
msgstr "Exibir imagem do autor"
#. Default: "show full comment text"
#: ../browser/moderation.pt:114
msgid "label_show_full_comment_text"
msgstr "Exibir texto completo"
#. Default: "Subject"
#: ../interfaces.py:158
msgid "label_subject"
msgstr "Assunto"
#. Default: "Comment text transform"
#: ../interfaces.py:269
msgid "label_text_transform"
msgstr "Transformações aplicadas ao texto do comentário"
#. Default: "Enable user email notification"
#: ../interfaces.py:337
msgid "label_user_notification_enabled"
msgstr "Activar notificação de utilizadores por email"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n"
#: ../comment.py:61
#, fuzzy
msgid "mail_notification_message"
msgstr "Um comentário em '${title}' foi adicionado aqui: ${link}"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n\nApprove comment:\n${link_approve}\n\nDelete comment:\n${link_delete}\n"
#: ../comment.py:69
msgid "mail_notification_message_moderator"
msgstr ""
"Um comentário sobre '${title}' foi adicionado aqui: ${link}\n"
"\n"
"---\n"
"${text}\n"
"---\n"
"\n"
"Aprovar comentário:\n"
"${link_approve}\n"
"\n"
"Apagar comentário:\n"
"${link_delete}\n"
#. Default: "enable the 'Comment Review Workflow' for the Comment content type"
#: ../browser/moderation.pt:33
msgid "message_enable_comment_workflow"
msgstr "Ativar 'Workflow de Moderação de Comentários\" para o tipo de item Comentário"
#. Default: "Moderation workflow is disabled. You have to ${enable_comment_workflow} before you can moderate comments here."
#: ../browser/moderation.pt:33
msgid "message_moderation_disabled"
msgstr "A moderação está desativada. Tem de ${enable_comment_workflow} antes de poder moderar os comentários aqui."
#. Default: "No comments to moderate."
#: ../browser/moderation.pt:43
msgid "message_nothing_to_moderate"
msgstr "Nenhum comentário para moderação."
#. Default: "Bulk Actions"
#: ../browser/moderation.pt:64
msgid "title_bulkactions"
msgstr "Ações em massa"

View File

@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: plone.app.discussion\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI +ZONE\n"
"PO-Revision-Date: 2011-04-14 17:20-0300\n"
"Last-Translator: Andre Nogueira <andre@simplesconsultoria.com.br>\n"
"PO-Revision-Date: 2014-12-05 17:36+0200\n"
"Last-Translator: Joao Molon <jtmolon@hadi.com.br>\n"
"Language-Team: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
@ -15,103 +15,127 @@ msgstr ""
"Domain: plone.app.discussion\n"
"X-Poedit-Language: Português do Brasil\n"
#: ../comment.py:264
#: ../comment.py:359
msgid "A comment has been posted."
msgstr "Comentário adicionado."
#: ../interfaces.py:257
#: ../interfaces.py:144
msgid "A comment id unique to this conversation"
msgstr "Um comentário com ID exclusivo para esta conversação"
#: ../browser/comments.py:67
#: ../browser/comments.py:72
msgid "Add a comment"
msgstr "Adicionar comentário"
#: ../browser/controlpanel.py:62
#: ../browser/controlpanel.py:75
msgid "Anonymous Comments"
msgstr "Comentários Anônimos"
#: ../interfaces.py:282
msgid "Author name (for display)"
msgstr "Nome do autor (para exibição)"
#: ../browser/comments.py:248
#: ../browser/controlpanel.py:80
#: ../browser/comments.py:275
#: ../browser/controlpanel.py:93
msgid "Cancel"
msgstr "Cancelar"
#: ../browser/controlpanel.py:76
#: ../interfaces.py:184
msgid "Captcha"
msgstr ""
#: ../browser/controlpanel.py:89
msgid "Changes saved"
msgstr "Alterações salvas"
#: ../browser/moderation.py:133
#: ../browser/moderation.py:186
msgid "Comment approved."
msgstr "Comentário aprovado"
#: ../browser/moderation.py:94
#: ../contentrules.py:92
msgid "Comment author email"
msgstr "Email do autor do comentário"
#: ../contentrules.py:81
msgid "Comment author full name"
msgstr "Nome completo do autor do comentário"
#: ../contentrules.py:70
msgid "Comment author user name"
msgstr "Nome de usuário do autor do comentário"
#: ../browser/moderation.py:111
msgid "Comment deleted."
msgstr "Comentário excluído."
#: ../browser/controlpanel.py:63
#: ../contentrules.py:48
msgid "Comment id"
msgstr "Id do comentário"
#: ../contentrules.py:59
msgid "Comment text"
msgstr "Texto do comentário"
#: ../browser/controlpanel.py:76
msgid "Commenter Image"
msgstr "Imagedo autor"
msgstr "Imagem do autor"
msgid "Commenting infrastructure for Plone"
msgstr "Infraestrutura de comentários para o Plone"
#: ../interfaces.py:252
#: ../contentrules.py:47
msgid "Comments"
msgstr "Comentários"
#: ../interfaces.py:139
msgid "Conversation"
msgstr "Conversação"
#: ../interfaces.py:283
#: ../interfaces.py:177
msgid "Creation date"
msgstr "Data de criação"
#: ../interfaces.py:162
msgid "Date of the most recent comment"
msgstr "Data do comentário mais recente"
#: ../interfaces.py:41
msgid "Date of the most recent public comment"
msgstr "Data do comentário, público, mais recente"
#: ../vocabularies.py:44
msgid "Disabled"
msgstr "Desativado"
#: ../browser/controlpanel.py:32
#: ../browser/controlpanel.py:33
msgid "Discussion settings"
msgstr "Configurações da discussão"
#: ../browser/controlpanel.py:82
#: ../browser/controlpanel.py:95
msgid "Edit cancelled"
msgstr "Edição cancelada"
#: ../interfaces.py:269
#: ../interfaces.py:156
msgid "Email"
msgstr "E-mail"
#: ../browser/controlpanel.py:61
#: ../browser/controlpanel.py:74
msgid "Enable Comments"
msgstr "Permitir comentários"
#: ../interfaces.py:260
#: ../interfaces.py:147
msgid "Id of comment this comment is in reply to"
msgstr "ID do comentário para qual este comentário é resposta"
#: ../interfaces.py:274
#: ../interfaces.py:161
msgid "MIME type"
msgstr "MIME type"
#: ../browser/controlpanel.py:65
#: ../browser/controlpanel.py:78
msgid "Moderator Email Notification"
msgstr "Notificação de e-mail para o moderador"
#: ../interfaces.py:284
#: ../interfaces.py:178
msgid "Modification date"
msgstr "Data de modificação"
#: ../interfaces.py:254
#: ../interfaces.py:141
msgid "Name"
msgstr "Nome"
#: ../interfaces.py:278
#: ../interfaces.py:170
msgid "Notify me of new comments via email."
msgstr "Receber avisos por e-mail para novos comentários."
@ -119,32 +143,44 @@ msgstr "Receber avisos por e-mail para novos comentários."
msgid "Plone Discussions"
msgstr "Plone Discussions"
#: ../interfaces.py:247
#: ../interfaces.py:134
msgid "Portal type"
msgstr "Tipo de objeto"
#: ../browser/controlpanel.py:69
#: ../browser/controlpanel.py:82
msgid "Save"
msgstr "Salvar"
#: ../interfaces.py:167
#: ../interfaces.py:46
msgid "The set of unique commentators (usernames)"
msgstr "Lista de usuários que fizeram comentários (nome de usuário)"
#: ../interfaces.py:156
msgid "Total number of comments on this item"
msgstr "Número total de comentários para este item"
#: ../interfaces.py:51
msgid "The set of unique commentators (usernames) of published_comments"
msgstr "O grupo de comentadoristas (nomes de usuários) com comentários publicados"
#: ../browser/controlpanel.py:67
#: ../interfaces.py:35
msgid "Total number of public comments on this item"
msgstr "Número total de comentários públicos neste item"
#: ../comment.py:175
msgid "Transform '%s' => '%s' not available."
msgstr "Transformação '%s' => '%s' não disponível"
#: ../browser/controlpanel.py:80
msgid "User Email Notification"
msgstr "Notificação de e-mail para o usuário"
#: ../browser/comments.py:241
#: ../interfaces.py:176
msgid "Username of the commenter"
msgstr "Nome de usuário do comentarista"
#: ../browser/comments.py:268
msgid "Your comment awaits moderator approval."
msgstr "Seu comentário está pendente e aguarda a aprovação do moderador."
#. Default: "Comment"
#: ../browser/comments.py:123
#: ../browser/comments.py:138
msgid "add_comment_button"
msgstr "Comentar"
@ -158,25 +194,55 @@ msgstr "Excluir"
msgid "bulkactions_publish"
msgstr "Publicar"
#. Default: "Cancel"
#: ../browser/comment.py:97
msgid "cancel_form_button"
msgstr "Cancelar"
#. Default: "You can add a comment by filling out the form below. Plain text formatting. Web and email addresses are transformed into clickable links."
#: ../browser/comments.py:52
#: ../browser/comments.py:57
msgid "comment_description_intelligent_text"
msgstr "Você pode adicionar um comentário preenchendo o formulário a seguir. Campo de texto simples. Endereços web e e-mail são transformados em links clicáveis."
#. Default: "You can add a comment by filling out the form below. Plain text formatting. You can use the Markdown syntax for links and images."
#: ../browser/comments.py:51
msgid "comment_description_markdown"
msgstr "Você pode adicionar um comentário preenchendo o formulário abaixo. Use apenas texto sem formatação. Você pode utilizar a sintaxe Markdown para links e imagens."
#. Default: "Comments are moderated."
#: ../browser/comments.py:58
#: ../browser/comments.py:63
msgid "comment_description_moderation_enabled"
msgstr "Os comentários são moderados"
#. Default: "You can add a comment by filling out the form below. Plain text formatting."
#: ../browser/comments.py:47
#: ../browser/comments.py:46
msgid "comment_description_plain_text"
msgstr "Você pode adicionar um comentário preenchendo o formulário a seguir. Campo de texto simples."
#. Default: "${creator} on ${content}"
#: ../comment.py:46
#. Default: "Edit comment cancelled"
#: ../browser/comment.py:101
msgid "comment_edit_cancel_notification"
msgstr "Edição do comentário cancelada"
#. Default: "Comment was edited"
#: ../browser/comment.py:91
msgid "comment_edit_notification"
msgstr "Comentário foi editado"
#. Default: "${author_name} on ${content}"
#: ../comment.py:57
msgid "comment_title"
msgstr "${creator} em ${content}"
msgstr "${author_name} em ${content}"
#. Default: "Edit comment"
#: ../browser/comment.py:70
msgid "edit_comment_form_button"
msgstr "Editar comentário"
#. Default: "Edit comment"
#: ../browser/comment.py:54
msgid "edit_comment_form_title"
msgstr "Editar cometário"
#. Default: "Action"
#: ../browser/moderation.pt:85
@ -209,85 +275,107 @@ msgid "heading_moderate_comments"
msgstr "Moderar comentários"
#. Default: "If selected, anonymous users are able to post comments without loggin in. It is highly recommended to use a captcha solution to prevent spam if this setting is enabled."
#: ../interfaces.py:38
#: ../interfaces.py:216
msgid "help_anonymous_comments"
msgstr "Se selecionado, usuários anonimos poderão adicionar comentários sem precisar de usuário e senha. É altamente recomendável a utilização de uma solução de captcha para evitar spam caso esta configuração esteja ativada."
#. Default: "If selected, anonymous user will have to give their email."
#: ../interfaces.py:352
msgid "help_anonymous_email_enabled"
msgstr "Caso selecionado, usuários anônimos devem informar um email."
#. Default: "Use this setting to enable or disable Captcha validation for comments. Install plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet, or collective.z3cform.norobots if there are no options available."
#: ../interfaces.py:82
#: ../interfaces.py:288
msgid "help_captcha"
msgstr "Utilize esta opção para ativar ou desativar o Captcha para os comentários. Instale plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet ou collective.z3cform.norobots caso não tenha nenhuma opção disponível."
#. Default: "If selected, supports deleting of own comments for users with the 'Delete own comments' permission."
#: ../interfaces.py:260
msgid "help_delete_own_comment_enabled"
msgstr ""
#. Default: "Some discussion related settings are not located in the Discussion Control Panel.\nTo enable comments for a specific content type, go to the Types Control Panel of this type and choose \"Allow comments\".\nTo enable the moderation workflow for comments, go to the Types Control Panel, choose \"Comment\" and set workflow to \"Comment Review Workflow\"."
#: ../browser/controlpanel.py:33
#: ../browser/controlpanel.py:34
msgid "help_discussion_settings_editform"
msgstr ""
"Algumas configurações relacionadas a comentários não estão localizadas no Painel de Controle de Comentários.\n"
"Para habilitar comentários para um tipo de item específico, vá até a configuração de Tipos no Painel de Controle, encontre o tipo desejado e selecione \"Permitir comentários \".\n"
"Para ativar o workflow de moderação de comentários, vá até a configuração de Tipos no Painel de Controle, escolha \"Comentário\" e selecione o workflow para \"Workflow de Revisão de Comentários\"."
#. Default: "If selected, supports editing of comments for users with the 'Edit comments' permission."
#: ../interfaces.py:249
#, fuzzy
msgid "help_edit_comment_enabled"
msgstr "Caso selecionado, permite a edição e remoção de comentários por usuários com a permissão 'Editar comentários'"
#. Default: "If selected, users are able to post comments on the site. Though, you have to enable comments for specific content types, folders or content objects before users will be able to post comments."
#: ../interfaces.py:26
#: ../interfaces.py:202
msgid "help_globally_enabled"
msgstr "Caso selecionado, permite que os visitantes adicionem comentários ao site. Porém, você deve habilitar comentários para cada tipo de conteúdo antes que os usuários possam adicionar comentários."
#. Default: "If selected, comments will enter a 'Pending' state in which they are invisible to the public. A user with the 'Review comments' permission ('Reviewer' or 'Manager') can approve comments to make them visible to the public. If you want to enable a custom comment workflow, you have to go to the types control panel."
#: ../interfaces.py:50
#: ../interfaces.py:232
msgid "help_moderation_enabled"
msgstr "Caso selecionado, os comentários serão adicionados no estado \"Pendente\", que é invisível ao público. Usuários com permissão para 'Revisar Comentários' ('Revisor' ou 'Administrador') podem aprovar os comentários para torná-los visíveis ao público. Caso queira ativar um workflow de comentários personalizado, você deve ir até a Configuração dos Tipos no Painel de Controle."
#. Default: "Address to which moderator notifications will be sent."
#: ../interfaces.py:118
#: ../interfaces.py:329
msgid "help_moderator_email"
msgstr "Endereço para o qual as notificações do moderador serão enviadas."
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be found in the 'Mail settings' control panel (Site 'From' address)"
#: ../interfaces.py:107
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be set below."
#: ../interfaces.py:315
msgid "help_moderator_notification_enabled"
msgstr "Se selecionado, o moderador será avisado quando um comentário precisar de atenção. O endereço de e-mail do moderador pode ser encontrado nas configurações de e-mail no Painel de Controle (campo Endereço de 'Remetente' do site)"
msgstr "Se selecionado, o moderador será avisado quando um comentário precisar de atenção. O endereço de e-mail do moderador pode ser definido abaixo."
#. Default: "If selected, an image of the user is shown next to the comment."
#: ../interfaces.py:97
#: ../interfaces.py:304
msgid "help_show_commenter_image"
msgstr "Se selecionado, uma imagem do usuário será exibida próxima ao comentário."
#. Default: "Use this setting to choose if the comment text should be transformed in any way. You can choose between 'Plain text' and 'Intelligent text'. 'Intelligent text' converts plain text into HTML where line breaks and indentation is preserved, and web and email addresses are made into clickable links."
#: ../interfaces.py:66
#: ../interfaces.py:271
msgid "help_text_transform"
msgstr "Use esta configuração para escolher se o texto do comentário deve ser transformado. Você pode escolher entre 'texto puro' e 'texto inteligente'. 'Texto inteligente' converte texto simples em HTML, onde as quebras de linha e os recuos são preservados, e os endereços web e e-mail são transformados em links clicáveis."
#. Default: "If selected, users can choose to be notified of new comments by email."
#: ../interfaces.py:127
#: ../interfaces.py:341
msgid "help_user_notification_enabled"
msgstr "Se selecionado, permite aos usuários solicitar o recebimento de avisos por e-mail sempre que hover um novo comentário."
#. Default: "Anonymous"
#: ../comment.py:156
#: ../browser/comments.pt:75
#: ../comment.py:193
msgid "label_anonymous"
msgstr "Anônimo"
#. Default: "Enable anonymous comments"
#: ../interfaces.py:36
#: ../interfaces.py:214
msgid "label_anonymous_comments"
msgstr "Permitir comentários anônimos."
#. Default: "Enable anonymous email field"
#: ../interfaces.py:350
msgid "label_anonymous_email_enabled"
msgstr "Habilitar campo de email para usuários anônimos"
#. Default: "Apply"
#: ../browser/moderation.pt:71
msgid "label_apply"
msgstr "Aplicar"
#. Default: "Captcha"
#: ../interfaces.py:80
#: ../interfaces.py:286
msgid "label_captcha"
msgstr "Captcha"
#. Default: "Comment"
#: ../interfaces.py:275
#: ../interfaces.py:163
msgid "label_comment"
msgstr "Comentário"
#. Default: "Commenting has been disabled."
#: ../browser/comments.pt:130
#: ../browser/comments.pt:163
msgid "label_commenting_disabled"
msgstr "Comentários foram desativados."
@ -296,23 +384,33 @@ msgstr "Comentários foram desativados."
msgid "label_delete"
msgstr "Excluir"
#. Default: "Enable deleting own comments"
#: ../interfaces.py:258
msgid "label_delete_own_comment_enabled"
msgstr ""
#. Default: "Enable editing of comments"
#: ../interfaces.py:247
msgid "label_edit_comment_enabled"
msgstr "Habilitar edição de comentários"
#. Default: "Globally enable comments"
#: ../interfaces.py:24
#: ../interfaces.py:200
msgid "label_globally_enabled"
msgstr "Ativar comentários globalmente"
#. Default: "Enable comment moderation"
#: ../interfaces.py:48
#: ../interfaces.py:228
msgid "label_moderation_enabled"
msgstr "Ativar moderação de comentários"
#. Default: "Moderator Email Address"
#: ../interfaces.py:117
#: ../interfaces.py:325
msgid "label_moderator_email"
msgstr "Endereço de e-mail do moderador"
#. Default: "Enable moderator email notification"
#: ../interfaces.py:105
#: ../interfaces.py:313
msgid "label_moderator_notification_enabled"
msgstr "Ativar notificação ao moderador"
@ -322,12 +420,12 @@ msgid "label_publish"
msgstr "Aprovar"
#. Default: "says:"
#: ../browser/comments.pt:74
#: ../browser/comments.pt:78
msgid "label_says"
msgstr "disse:"
#. Default: "Show commenter image"
#: ../interfaces.py:95
#: ../interfaces.py:302
msgid "label_show_commenter_image"
msgstr "Exibir imagem do autor"
@ -337,30 +435,44 @@ msgid "label_show_full_comment_text"
msgstr "Exibir texto completo"
#. Default: "Subject"
#: ../interfaces.py:271
#: ../interfaces.py:158
msgid "label_subject"
msgstr "Assunto"
#. Default: "Comment text transform"
#: ../interfaces.py:64
#: ../interfaces.py:269
msgid "label_text_transform"
msgstr "Transformações aplicadas ao texto do comentário"
#. Default: "Enable user email notification"
#: ../interfaces.py:125
#: ../interfaces.py:337
msgid "label_user_notification_enabled"
msgstr "Ativar notificação de e-mail para os usuários"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n"
#: ../comment.py:50
#, fuzzy
#: ../comment.py:61
msgid "mail_notification_message"
msgstr "Um comentário em '${title}' foi adicionado aqui: ${link}"
msgstr ""
"Um comentário em '${title}' foi adicionado aqui: ${link}\n"
"\n"
"---\n"
"{text}\n"
"---\n"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n\nApprove comment:\n${link_approve}\n\nDelete comment:\n${link_delete}\n"
#: ../comment.py:58
#: ../comment.py:69
msgid "mail_notification_message_moderator"
msgstr ""
"Um comentário no conteúdo '${title}' foi adicionado em: ${link}\n"
"\n"
"---\n"
"${text}\n"
"---\n"
"\Aprove o comentário:\n"
"${link_approve}\n"
"\n"
"Remova o comentário:\n"
"${link_delete}\n"
#. Default: "enable the 'Comment Review Workflow' for the Comment content type"
#: ../browser/moderation.pt:33

View File

@ -0,0 +1,497 @@
# David Ichim <ichim.david@gmail.com>, 2013.
msgid ""
msgstr ""
"Project-Id-Version: plone.app.discussion\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI +ZONE\n"
"PO-Revision-Date: 2013-02-03 15:33-0600\n"
"Last-Translator: David Ichim <ichim.david@gmail.com>\n"
"Language-Team: ro <ro@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"Language-Code: ro\n"
"Language-Name: Romanian\n"
"Preferred-Encodings: utf-8 latin1\n"
"Domain: plone.app.discussion\n"
#: ../comment.py:359
msgid "A comment has been posted."
msgstr "Un comentariu a fost postat."
#: ../interfaces.py:144
msgid "A comment id unique to this conversation"
msgstr "Un id de comentariu unic pentru aceasta conversatie"
#: ../browser/comments.py:72
msgid "Add a comment"
msgstr "Adauga comentariu"
#: ../browser/controlpanel.py:75
msgid "Anonymous Comments"
msgstr "Comentarii de la anonimi"
#: ../browser/comments.py:275
#: ../browser/controlpanel.py:93
msgid "Cancel"
msgstr "Anuleaza"
#: ../interfaces.py:184
msgid "Captcha"
msgstr ""
#: ../browser/controlpanel.py:89
msgid "Changes saved"
msgstr "Schimbari salvate"
#: ../browser/moderation.py:186
msgid "Comment approved."
msgstr "Comentariul a fost aprobat."
#: ../contentrules.py:92
msgid "Comment author email"
msgstr ""
#: ../contentrules.py:81
msgid "Comment author full name"
msgstr ""
#: ../contentrules.py:70
msgid "Comment author user name"
msgstr ""
#: ../browser/moderation.py:111
msgid "Comment deleted."
msgstr "Comentariul a fost sters."
#: ../contentrules.py:48
msgid "Comment id"
msgstr ""
#: ../contentrules.py:59
msgid "Comment text"
msgstr ""
#: ../browser/controlpanel.py:76
msgid "Commenter Image"
msgstr "Imaginea comentatorului"
msgid "Commenting infrastructure for Plone"
msgstr "Infrastructura de comentarii pentru Plone"
#: ../contentrules.py:47
msgid "Comments"
msgstr ""
#: ../interfaces.py:139
msgid "Conversation"
msgstr "Conversatie"
#: ../interfaces.py:177
msgid "Creation date"
msgstr "Data creerii"
#: ../interfaces.py:41
msgid "Date of the most recent public comment"
msgstr ""
#: ../vocabularies.py:44
msgid "Disabled"
msgstr "Dezactivat"
#: ../browser/controlpanel.py:33
msgid "Discussion settings"
msgstr "Setarile Discutiilor"
#: ../browser/controlpanel.py:95
msgid "Edit cancelled"
msgstr "Editare anulata"
#: ../interfaces.py:156
msgid "Email"
msgstr "Email"
#: ../browser/controlpanel.py:74
msgid "Enable Comments"
msgstr "Permite Comentarii"
#: ../interfaces.py:147
msgid "Id of comment this comment is in reply to"
msgstr "Id-ul comentariului pentru care acest comentariu raspunde"
#: ../interfaces.py:161
msgid "MIME type"
msgstr "Tip MIME"
#: ../browser/controlpanel.py:78
msgid "Moderator Email Notification"
msgstr "Notificare Moderatorului prin Email"
#: ../interfaces.py:178
msgid "Modification date"
msgstr "Data modificarii"
#: ../interfaces.py:141
msgid "Name"
msgstr "Nume"
#: ../interfaces.py:170
msgid "Notify me of new comments via email."
msgstr "Anuntama de noi comentarii prin email."
#: ./plone.app.discussion/plone/app/discussion/configure.zcml
msgid "Plone Discussions"
msgstr "Discutii Plone"
#: ../interfaces.py:134
msgid "Portal type"
msgstr "Tip obiect"
#: ../browser/controlpanel.py:82
msgid "Save"
msgstr "Salveaza"
#: ../interfaces.py:46
msgid "The set of unique commentators (usernames)"
msgstr "Setul comentatorilor unici (nume de utilizator)"
#: ../interfaces.py:51
msgid "The set of unique commentators (usernames) of published_comments"
msgstr ""
#: ../interfaces.py:35
msgid "Total number of public comments on this item"
msgstr ""
#: ../comment.py:175
msgid "Transform '%s' => '%s' not available."
msgstr ""
#: ../browser/controlpanel.py:80
msgid "User Email Notification"
msgstr "Notificarea utilizatorului prin email"
#: ../interfaces.py:176
msgid "Username of the commenter"
msgstr ""
#: ../browser/comments.py:268
msgid "Your comment awaits moderator approval."
msgstr "Comentariul tau asteapta sa fie moderat."
#. Default: "Comment"
#: ../browser/comments.py:138
msgid "add_comment_button"
msgstr "Comentariu"
#. Default: "Delete"
#: ../browser/moderation.pt:68
msgid "bulkactions_delete"
msgstr "Sterge"
#. Default: "Approve"
#: ../browser/moderation.pt:65
msgid "bulkactions_publish"
msgstr "Aproba"
#. Default: "Cancel"
#: ../browser/comment.py:97
msgid "cancel_form_button"
msgstr ""
#. Default: "You can add a comment by filling out the form below. Plain text formatting. Web and email addresses are transformed into clickable links."
#: ../browser/comments.py:57
msgid "comment_description_intelligent_text"
msgstr "Poti adauga un comentariu completand formularul de mai jos. Formatare de text simpla doar. Adresele de email si web sunt transformate in link-uri."
#. Default: "You can add a comment by filling out the form below. Plain text formatting. You can use the Markdown syntax for links and images."
#: ../browser/comments.py:51
msgid "comment_description_markdown"
msgstr ""
#. Default: "Comments are moderated."
#: ../browser/comments.py:63
msgid "comment_description_moderation_enabled"
msgstr "Comentariile sunt moderate."
#. Default: "You can add a comment by filling out the form below. Plain text formatting."
#: ../browser/comments.py:46
msgid "comment_description_plain_text"
msgstr "Poti adauga un comentariu prin completarea formularului de mai jos. Format de text simplu doar."
#. Default: "Edit comment cancelled"
#: ../browser/comment.py:101
msgid "comment_edit_cancel_notification"
msgstr ""
#. Default: "Comment was edited"
#: ../browser/comment.py:91
msgid "comment_edit_notification"
msgstr ""
#. Default: "${author_name} on ${content}"
#: ../comment.py:57
#, fuzzy
msgid "comment_title"
msgstr "${creator} al ${content}"
#. Default: "Edit comment"
#: ../browser/comment.py:70
msgid "edit_comment_form_button"
msgstr ""
#. Default: "Edit comment"
#: ../browser/comment.py:54
msgid "edit_comment_form_title"
msgstr ""
#. Default: "Action"
#: ../browser/moderation.pt:85
msgid "heading_action"
msgstr "Actiune"
#. Default: "Comment"
#: ../browser/moderation.pt:84
msgid "heading_comment"
msgstr "Comentariu"
#. Default: "Commenter"
#: ../browser/moderation.pt:81
msgid "heading_commenter"
msgstr "Autor"
#. Default: "Date"
#: ../browser/moderation.pt:82
msgid "heading_date"
msgstr "Data"
#. Default: "In Response To"
#: ../browser/moderation.pt:83
msgid "heading_in_reponse_to"
msgstr "In raspuns lui"
#. Default: "Moderate comments"
#: ../browser/moderation.pt:24
msgid "heading_moderate_comments"
msgstr "Modereaza comentarii"
#. Default: "If selected, anonymous users are able to post comments without loggin in. It is highly recommended to use a captcha solution to prevent spam if this setting is enabled."
#: ../interfaces.py:216
msgid "help_anonymous_comments"
msgstr "Daca selectat, utilizatorii anonimi vor putea posta comentarii fara a fi autentificati. Este recomandat a se folosi o solutie captcha pentru a preveni spam-ul daca aceasta setare este activata."
#. Default: "If selected, anonymous user will have to give their email."
#: ../interfaces.py:352
msgid "help_anonymous_email_enabled"
msgstr ""
#. Default: "Use this setting to enable or disable Captcha validation for comments. Install plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet, or collective.z3cform.norobots if there are no options available."
#: ../interfaces.py:288
msgid "help_captcha"
msgstr "Foloseste aceasta setare pentru a activa sau dezactiva validarea Captcha a comentariilor. Instaleaza plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet sau collective.z3cform.norobots daca nu este nici o optiune disponibila."
#. Default: "If selected, supports deleting of own comments for users with the 'Delete own comments' permission."
#: ../interfaces.py:260
msgid "help_delete_own_comment_enabled"
msgstr ""
#. Default: "Some discussion related settings are not located in the Discussion Control Panel.\nTo enable comments for a specific content type, go to the Types Control Panel of this type and choose \"Allow comments\".\nTo enable the moderation workflow for comments, go to the Types Control Panel, choose \"Comment\" and set workflow to \"Comment Review Workflow\"."
#: ../browser/controlpanel.py:34
msgid "help_discussion_settings_editform"
msgstr ""
"Unele setari legate de discutii nu sunt localizate in Panoul de Discutii.\n"
"Pentru a activa comentarii pentru un tip specific de obiect, dute la Panoul de Control al Tipurilor pentru acest obiect si selecteaza \"Permite comentarii\".\n"
"Pentru a alege workflow-ul de moderare pentru comentarii, dute la Panoul de Control pentru Tipuri de obiect, alege \"Comentariu\" si seteaza workflow-ul la \"Workflow de moderare al Comentariilor\"."
#. Default: "If selected, supports editing of comments for users with the 'Edit comments' permission."
#: ../interfaces.py:249
msgid "help_edit_comment_enabled"
msgstr ""
#. Default: "If selected, users are able to post comments on the site. Though, you have to enable comments for specific content types, folders or content objects before users will be able to post comments."
#: ../interfaces.py:202
msgid "help_globally_enabled"
msgstr "Daca selectat, utilizatorii pot posta comentarii in acest site. Totusi, trebuie sa activezi comentariile pentru tipurile de obiecte in mod specific, fie directoare sau alte tipurile de obiect inainte ca utilizatorii sa poata posta comentarii."
#. Default: "If selected, comments will enter a 'Pending' state in which they are invisible to the public. A user with the 'Review comments' permission ('Reviewer' or 'Manager') can approve comments to make them visible to the public. If you want to enable a custom comment workflow, you have to go to the types control panel."
#: ../interfaces.py:232
msgid "help_moderation_enabled"
msgstr "Daca selectat, comentariile vor intra intr-o stare de 'Asteptare' in care ele sunt invizibile publicului. Un utilizator cu permisia 'Modereaza Comentarii' ('Moderator' sau 'Manager') poate aprova comentariile pentru a le face vizibile publicului. Daca doresti sa activezi un workflow de comentariu specific, trebuie sa mergi la panoul de control al obiectelor"
#. Default: "Address to which moderator notifications will be sent."
#: ../interfaces.py:329
msgid "help_moderator_email"
msgstr "Adresa de email la care notificarile de moderare vor fi trimise."
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be set below."
#: ../interfaces.py:315
#, fuzzy
msgid "help_moderator_notification_enabled"
msgstr "Daca selectat, moderatorul este notificat daca un comentariu are nevoie de atentie. Adresa de email al moderatorului poate fi gasita in panoul de control numit 'Setari mail' (Adresa 'De la' pentru Site)"
#. Default: "If selected, an image of the user is shown next to the comment."
#: ../interfaces.py:304
msgid "help_show_commenter_image"
msgstr "Daca selectat, o imagine al utilizatorului este afisata langa comentariul sau."
#. Default: "Use this setting to choose if the comment text should be transformed in any way. You can choose between 'Plain text' and 'Intelligent text'. 'Intelligent text' converts plain text into HTML where line breaks and indentation is preserved, and web and email addresses are made into clickable links."
#: ../interfaces.py:271
msgid "help_text_transform"
msgstr "Foloseste aceasta setare pentru a alege daca textul comentariului ar trebui sa fie transformat intr-un fel. Poti alege intre 'Text simplu' si 'Text inteligent'. 'Text inteligent' transforma textul simplu in HTML unde indentarea si liniile sunt pastrate si adresele de email si web sunt transformate in link-uri."
#. Default: "If selected, users can choose to be notified of new comments by email."
#: ../interfaces.py:341
msgid "help_user_notification_enabled"
msgstr "Daca selectat, utilizatorii pot alege sa fie notificati de noi comentarii prin email."
#. Default: "Anonymous"
#: ../browser/comments.pt:75
#: ../comment.py:193
msgid "label_anonymous"
msgstr "Anonimi"
#. Default: "Enable anonymous comments"
#: ../interfaces.py:214
msgid "label_anonymous_comments"
msgstr "Permite comentariile anonime"
#. Default: "Enable anonymous email field"
#: ../interfaces.py:350
msgid "label_anonymous_email_enabled"
msgstr ""
#. Default: "Apply"
#: ../browser/moderation.pt:71
msgid "label_apply"
msgstr "Aplica"
#. Default: "Captcha"
#: ../interfaces.py:286
msgid "label_captcha"
msgstr "Captcha"
#. Default: "Comment"
#: ../interfaces.py:163
msgid "label_comment"
msgstr "Comentariu"
#. Default: "Commenting has been disabled."
#: ../browser/comments.pt:163
msgid "label_commenting_disabled"
msgstr "Comentariile au fost dezactivate."
#. Default: "Delete"
#: ../browser/moderation.pt:130
msgid "label_delete"
msgstr "Sterge"
#. Default: "Enable deleting own comments"
#: ../interfaces.py:258
msgid "label_delete_own_comment_enabled"
msgstr ""
#. Default: "Enable editing of comments"
#: ../interfaces.py:247
msgid "label_edit_comment_enabled"
msgstr ""
#. Default: "Globally enable comments"
#: ../interfaces.py:200
msgid "label_globally_enabled"
msgstr "Activeaza comentariile in mod global"
#. Default: "Enable comment moderation"
#: ../interfaces.py:228
msgid "label_moderation_enabled"
msgstr "Activeaza moderarea comentariilor"
#. Default: "Moderator Email Address"
#: ../interfaces.py:325
msgid "label_moderator_email"
msgstr "Adresa de email al moderatorului de comentarii"
#. Default: "Enable moderator email notification"
#: ../interfaces.py:313
msgid "label_moderator_notification_enabled"
msgstr "Activeaza notificarea moderatorului de comentarii prin email"
#. Default: "Approve"
#: ../browser/moderation.pt:121
msgid "label_publish"
msgstr "Aproba"
#. Default: "says:"
#: ../browser/comments.pt:78
msgid "label_says"
msgstr "zice:"
#. Default: "Show commenter image"
#: ../interfaces.py:302
msgid "label_show_commenter_image"
msgstr "Arata imaginea comentatorului"
#. Default: "show full comment text"
#: ../browser/moderation.pt:114
msgid "label_show_full_comment_text"
msgstr "Arata textul intreg al comentariului"
#. Default: "Subject"
#: ../interfaces.py:158
msgid "label_subject"
msgstr "Subiect"
#. Default: "Comment text transform"
#: ../interfaces.py:269
msgid "label_text_transform"
msgstr "Transformarea textului comentariului"
#. Default: "Enable user email notification"
#: ../interfaces.py:337
msgid "label_user_notification_enabled"
msgstr "Activeaza notificarea utilizatorului prin email"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n"
#: ../comment.py:61
msgid "mail_notification_message"
msgstr ""
"Un comentariu pe '${title}' a fost postat aici: ${link}\n"
"\n"
"---\n"
"${text}\n"
"---\n"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n\nApprove comment:\n${link_approve}\n\nDelete comment:\n${link_delete}\n"
#: ../comment.py:69
msgid "mail_notification_message_moderator"
msgstr ""
"Un comentariu pe '${title}' a fost postat aici: ${link}\n"
"\n"
"---\n"
"${text}\n"
"---\n"
"Aproba comentariul:\n"
"${link_approve}\n"
"\n"
"Sterge comentariul:\n"
"${link_delete}\n"
#. Default: "enable the 'Comment Review Workflow' for the Comment content type"
#: ../browser/moderation.pt:33
msgid "message_enable_comment_workflow"
msgstr "Activeaza 'Workflow-ul de Moderare al Comentariilor' pentru tipul de obiect Comentariu"
#. Default: "Moderation workflow is disabled. You have to ${enable_comment_workflow} before you can moderate comments here."
#: ../browser/moderation.pt:33
msgid "message_moderation_disabled"
msgstr "Workflow-ul de Moderare este dezactivat. Trebuie sa ${enable_comment_workflow} inainte de a putea modera comentarii aici."
#. Default: "No comments to moderate."
#: ../browser/moderation.pt:43
msgid "message_nothing_to_moderate"
msgstr "Nici un comentariu nu a fost introdus pentru moderare."
#. Default: "Bulk Actions"
#: ../browser/moderation.pt:64
msgid "title_bulkactions"
msgstr "Actiuni in masa"

View File

@ -14,11 +14,11 @@ msgstr ""
"Preferred-Encodings: utf-8 latin1\n"
"Domain: plone.app.discussion\n"
#: ../comment.py:290
#: ../comment.py:359
msgid "A comment has been posted."
msgstr ""
#: ../interfaces.py:135
#: ../interfaces.py:144
msgid "A comment id unique to this conversation"
msgstr ""
@ -26,91 +26,115 @@ msgstr ""
msgid "Add a comment"
msgstr ""
#: ../browser/controlpanel.py:64
#: ../browser/controlpanel.py:75
msgid "Anonymous Comments"
msgstr ""
#: ../interfaces.py:160
msgid "Author name (for display)"
msgstr ""
#: ../browser/comments.py:243
#: ../browser/controlpanel.py:82
#: ../browser/comments.py:275
#: ../browser/controlpanel.py:93
msgid "Cancel"
msgstr ""
#: ../browser/controlpanel.py:78
#: ../interfaces.py:184
msgid "Captcha"
msgstr ""
#: ../browser/controlpanel.py:89
msgid "Changes saved"
msgstr ""
#: ../browser/moderation.py:138
#: ../browser/moderation.py:186
msgid "Comment approved."
msgstr ""
#: ../browser/moderation.py:99
#: ../contentrules.py:92
msgid "Comment author email"
msgstr ""
#: ../contentrules.py:81
msgid "Comment author full name"
msgstr ""
#: ../contentrules.py:70
msgid "Comment author user name"
msgstr ""
#: ../browser/moderation.py:111
msgid "Comment deleted."
msgstr ""
#: ../browser/controlpanel.py:65
#: ../contentrules.py:48
msgid "Comment id"
msgstr ""
#: ../contentrules.py:59
msgid "Comment text"
msgstr ""
#: ../browser/controlpanel.py:76
msgid "Commenter Image"
msgstr ""
msgid "Commenting infrastructure for Plone"
msgstr ""
#: ../interfaces.py:130
#: ../contentrules.py:47
msgid "Comments"
msgstr ""
#: ../interfaces.py:139
msgid "Conversation"
msgstr ""
#: ../interfaces.py:161
#: ../interfaces.py:177
msgid "Creation date"
msgstr ""
#: ../interfaces.py:40
msgid "Date of the most recent comment"
#: ../interfaces.py:41
msgid "Date of the most recent public comment"
msgstr ""
#: ../vocabularies.py:44
msgid "Disabled"
msgstr ""
#: ../browser/controlpanel.py:34
#: ../browser/controlpanel.py:33
msgid "Discussion settings"
msgstr ""
#: ../browser/controlpanel.py:84
#: ../browser/controlpanel.py:95
msgid "Edit cancelled"
msgstr ""
#: ../interfaces.py:147
#: ../interfaces.py:156
msgid "Email"
msgstr ""
#: ../browser/controlpanel.py:63
#: ../browser/controlpanel.py:74
msgid "Enable Comments"
msgstr ""
#: ../interfaces.py:138
#: ../interfaces.py:147
msgid "Id of comment this comment is in reply to"
msgstr ""
#: ../interfaces.py:152
#: ../interfaces.py:161
msgid "MIME type"
msgstr ""
#: ../browser/controlpanel.py:67
#: ../browser/controlpanel.py:78
msgid "Moderator Email Notification"
msgstr ""
#: ../interfaces.py:162
#: ../interfaces.py:178
msgid "Modification date"
msgstr ""
#: ../interfaces.py:132
#: ../interfaces.py:141
msgid "Name"
msgstr ""
#: ../interfaces.py:156
#: ../interfaces.py:170
msgid "Notify me of new comments via email."
msgstr ""
@ -118,32 +142,44 @@ msgstr ""
msgid "Plone Discussions"
msgstr ""
#: ../interfaces.py:125
#: ../interfaces.py:134
msgid "Portal type"
msgstr ""
#: ../browser/controlpanel.py:71
#: ../browser/controlpanel.py:82
msgid "Save"
msgstr ""
#: ../interfaces.py:45
#: ../interfaces.py:46
msgid "The set of unique commentators (usernames)"
msgstr ""
#: ../interfaces.py:34
msgid "Total number of comments on this item"
#: ../interfaces.py:51
msgid "The set of unique commentators (usernames) of published_comments"
msgstr ""
#: ../browser/controlpanel.py:69
#: ../interfaces.py:35
msgid "Total number of public comments on this item"
msgstr ""
#: ../comment.py:175
msgid "Transform '%s' => '%s' not available."
msgstr ""
#: ../browser/controlpanel.py:80
msgid "User Email Notification"
msgstr ""
#: ../browser/comments.py:236
#: ../interfaces.py:176
msgid "Username of the commenter"
msgstr ""
#: ../browser/comments.py:268
msgid "Your comment awaits moderator approval."
msgstr ""
#. Default: "Comment"
#: ../browser/comments.py:127
#: ../browser/comments.py:138
msgid "add_comment_button"
msgstr ""
@ -157,6 +193,11 @@ msgstr ""
msgid "bulkactions_publish"
msgstr ""
#. Default: "Cancel"
#: ../browser/comment.py:97
msgid "cancel_form_button"
msgstr ""
#. Default: "You can add a comment by filling out the form below. Plain text formatting. Web and email addresses are transformed into clickable links."
#: ../browser/comments.py:57
msgid "comment_description_intelligent_text"
@ -177,11 +218,31 @@ msgstr ""
msgid "comment_description_plain_text"
msgstr ""
#. Default: "${creator} on ${content}"
#: ../comment.py:46
#. Default: "Edit comment cancelled"
#: ../browser/comment.py:101
msgid "comment_edit_cancel_notification"
msgstr ""
#. Default: "Comment was edited"
#: ../browser/comment.py:91
msgid "comment_edit_notification"
msgstr ""
#. Default: "${author_name} on ${content}"
#: ../comment.py:57
msgid "comment_title"
msgstr ""
#. Default: "Edit comment"
#: ../browser/comment.py:70
msgid "edit_comment_form_button"
msgstr ""
#. Default: "Edit comment"
#: ../browser/comment.py:54
msgid "edit_comment_form_title"
msgstr ""
#. Default: "Action"
#: ../browser/moderation.pt:85
msgid "heading_action"
@ -213,82 +274,103 @@ msgid "heading_moderate_comments"
msgstr ""
#. Default: "If selected, anonymous users are able to post comments without loggin in. It is highly recommended to use a captcha solution to prevent spam if this setting is enabled."
#: ../interfaces.py:230
#: ../interfaces.py:216
msgid "help_anonymous_comments"
msgstr ""
#. Default: "If selected, anonymous user will have to give their email."
#: ../interfaces.py:352
msgid "help_anonymous_email_enabled"
msgstr ""
#. Default: "Use this setting to enable or disable Captcha validation for comments. Install plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet, or collective.z3cform.norobots if there are no options available."
#: ../interfaces.py:273
#: ../interfaces.py:288
msgid "help_captcha"
msgstr ""
#. Default: "If selected, supports deleting of own comments for users with the 'Delete own comments' permission."
#: ../interfaces.py:260
msgid "help_delete_own_comment_enabled"
msgstr ""
#. Default: "Some discussion related settings are not located in the Discussion Control Panel.\nTo enable comments for a specific content type, go to the Types Control Panel of this type and choose \"Allow comments\".\nTo enable the moderation workflow for comments, go to the Types Control Panel, choose \"Comment\" and set workflow to \"Comment Review Workflow\"."
#: ../browser/controlpanel.py:35
#: ../browser/controlpanel.py:34
msgid "help_discussion_settings_editform"
msgstr ""
#. Default: "If selected, supports editing of comments for users with the 'Edit comments' permission."
#: ../interfaces.py:249
msgid "help_edit_comment_enabled"
msgstr ""
#. Default: "If selected, users are able to post comments on the site. Though, you have to enable comments for specific content types, folders or content objects before users will be able to post comments."
#: ../interfaces.py:218
#: ../interfaces.py:202
msgid "help_globally_enabled"
msgstr ""
#. Default: "If selected, comments will enter a 'Pending' state in which they are invisible to the public. A user with the 'Review comments' permission ('Reviewer' or 'Manager') can approve comments to make them visible to the public. If you want to enable a custom comment workflow, you have to go to the types control panel."
#: ../interfaces.py:242
#: ../interfaces.py:232
msgid "help_moderation_enabled"
msgstr ""
#. Default: "Address to which moderator notifications will be sent."
#: ../interfaces.py:310
#: ../interfaces.py:329
msgid "help_moderator_email"
msgstr ""
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be found in the 'Mail settings' control panel (Site 'From' address)"
#: ../interfaces.py:298
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be set below."
#: ../interfaces.py:315
msgid "help_moderator_notification_enabled"
msgstr ""
#. Default: "If selected, an image of the user is shown next to the comment."
#: ../interfaces.py:288
#: ../interfaces.py:304
msgid "help_show_commenter_image"
msgstr ""
#. Default: "Use this setting to choose if the comment text should be transformed in any way. You can choose between 'Plain text' and 'Intelligent text'. 'Intelligent text' converts plain text into HTML where line breaks and indentation is preserved, and web and email addresses are made into clickable links."
#: ../interfaces.py:257
#: ../interfaces.py:271
msgid "help_text_transform"
msgstr ""
#. Default: "If selected, users can choose to be notified of new comments by email."
#: ../interfaces.py:319
#: ../interfaces.py:341
msgid "help_user_notification_enabled"
msgstr ""
#. Default: "Anonymous"
#: ../comment.py:158
#: ../browser/comments.pt:75
#: ../comment.py:193
msgid "label_anonymous"
msgstr ""
#. Default: "Enable anonymous comments"
#: ../interfaces.py:228
#: ../interfaces.py:214
msgid "label_anonymous_comments"
msgstr ""
#. Default: "Enable anonymous email field"
#: ../interfaces.py:350
msgid "label_anonymous_email_enabled"
msgstr ""
#. Default: "Apply"
#: ../browser/moderation.pt:71
msgid "label_apply"
msgstr ""
#. Default: "Captcha"
#: ../interfaces.py:271
#: ../interfaces.py:286
msgid "label_captcha"
msgstr ""
#. Default: "Comment"
#: ../interfaces.py:153
#: ../interfaces.py:163
msgid "label_comment"
msgstr ""
#. Default: "Commenting has been disabled."
#: ../browser/comments.pt:130
#: ../browser/comments.pt:163
msgid "label_commenting_disabled"
msgstr ""
@ -297,23 +379,33 @@ msgstr ""
msgid "label_delete"
msgstr ""
#. Default: "Enable deleting own comments"
#: ../interfaces.py:258
msgid "label_delete_own_comment_enabled"
msgstr ""
#. Default: "Enable editing of comments"
#: ../interfaces.py:247
msgid "label_edit_comment_enabled"
msgstr ""
#. Default: "Globally enable comments"
#: ../interfaces.py:216
#: ../interfaces.py:200
msgid "label_globally_enabled"
msgstr ""
#. Default: "Enable comment moderation"
#: ../interfaces.py:240
#: ../interfaces.py:228
msgid "label_moderation_enabled"
msgstr ""
#. Default: "Moderator Email Address"
#: ../interfaces.py:308
#: ../interfaces.py:325
msgid "label_moderator_email"
msgstr ""
#. Default: "Enable moderator email notification"
#: ../interfaces.py:296
#: ../interfaces.py:313
msgid "label_moderator_notification_enabled"
msgstr ""
@ -323,12 +415,12 @@ msgid "label_publish"
msgstr ""
#. Default: "says:"
#: ../browser/comments.pt:74
#: ../browser/comments.pt:78
msgid "label_says"
msgstr ""
#. Default: "Show commenter image"
#: ../interfaces.py:286
#: ../interfaces.py:302
msgid "label_show_commenter_image"
msgstr ""
@ -338,27 +430,27 @@ msgid "label_show_full_comment_text"
msgstr ""
#. Default: "Subject"
#: ../interfaces.py:149
#: ../interfaces.py:158
msgid "label_subject"
msgstr ""
#. Default: "Comment text transform"
#: ../interfaces.py:255
#: ../interfaces.py:269
msgid "label_text_transform"
msgstr ""
#. Default: "Enable user email notification"
#: ../interfaces.py:317
#: ../interfaces.py:337
msgid "label_user_notification_enabled"
msgstr ""
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n"
#: ../comment.py:50
#: ../comment.py:61
msgid "mail_notification_message"
msgstr ""
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n\nApprove comment:\n${link_approve}\n\nDelete comment:\n${link_delete}\n"
#: ../comment.py:58
#: ../comment.py:69
msgid "mail_notification_message_moderator"
msgstr ""

View File

@ -9,108 +9,134 @@ msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"Language-Code: en\n"
"Language-Name: English\n"
"Preferred-Encodings: utf-8 latin1\n"
"Domain: DOMAIN\n"
"X-Is-Fallback-For: sv-fi sv-se\n"
#: ../comment.py:264
#: ../comment.py:359
msgid "A comment has been posted."
msgstr "En kommentar har postats."
# kommentarstråd?
#: ../interfaces.py:257
#: ../interfaces.py:144
msgid "A comment id unique to this conversation"
msgstr "En id unik för denna kommentar"
#: ../browser/comments.py:67
#: ../browser/comments.py:72
msgid "Add a comment"
msgstr "Lägg till en kommentar"
#: ../browser/controlpanel.py:62
#: ../browser/controlpanel.py:75
msgid "Anonymous Comments"
msgstr "Anonym kommentar"
# synlig???
#: ../interfaces.py:282
msgid "Author name (for display)"
msgstr "Författarnamn (synlig)"
#: ../browser/comments.py:248
#: ../browser/controlpanel.py:80
#: ../browser/comments.py:275
#: ../browser/controlpanel.py:93
msgid "Cancel"
msgstr "Avbryt"
#: ../browser/controlpanel.py:76
#: ../interfaces.py:184
msgid "Captcha"
msgstr ""
#: ../browser/controlpanel.py:89
msgid "Changes saved"
msgstr "Ändringar sparade"
#: ../browser/moderation.py:133
#: ../browser/moderation.py:186
msgid "Comment approved."
msgstr "Kommentaren har nu godkänts."
#: ../browser/moderation.py:94
#: ../contentrules.py:92
msgid "Comment author email"
msgstr ""
#: ../contentrules.py:81
msgid "Comment author full name"
msgstr ""
#: ../contentrules.py:70
msgid "Comment author user name"
msgstr ""
#: ../browser/moderation.py:111
msgid "Comment deleted."
msgstr "Kommentaren har nu raderats."
#: ../browser/controlpanel.py:63
#: ../contentrules.py:48
msgid "Comment id"
msgstr ""
#: ../contentrules.py:59
msgid "Comment text"
msgstr ""
#: ../browser/controlpanel.py:76
msgid "Commenter Image"
msgstr "Porträtt av kommentatorn"
msgid "Commenting infrastructure for Plone"
msgstr "Infrastruktur för kommentarer i Plone"
#: ../interfaces.py:252
#: ../contentrules.py:47
msgid "Comments"
msgstr ""
#: ../interfaces.py:139
msgid "Conversation"
msgstr "Diskussion"
#: ../interfaces.py:283
#: ../interfaces.py:177
msgid "Creation date"
msgstr "Skapelsedatum"
#: ../interfaces.py:162
msgid "Date of the most recent comment"
msgstr "Datum för den senaste kommentaren"
#: ../interfaces.py:41
msgid "Date of the most recent public comment"
msgstr ""
#: ../vocabularies.py:44
msgid "Disabled"
msgstr "Inaktiverad"
#: ../browser/controlpanel.py:32
#: ../browser/controlpanel.py:33
msgid "Discussion settings"
msgstr "Inställningar för kommentarer"
#: ../browser/controlpanel.py:82
#: ../browser/controlpanel.py:95
msgid "Edit cancelled"
msgstr "Redigering avbruten"
#: ../interfaces.py:269
#: ../interfaces.py:156
msgid "Email"
msgstr "E-post"
#: ../browser/controlpanel.py:61
#: ../browser/controlpanel.py:74
msgid "Enable Comments"
msgstr "Aktivera kommentarer"
#: ../interfaces.py:260
#: ../interfaces.py:147
msgid "Id of comment this comment is in reply to"
msgstr "Id för den kommentar som denna kommentar besvarar"
#: ../interfaces.py:274
#: ../interfaces.py:161
msgid "MIME type"
msgstr "MIME-type"
#: ../browser/controlpanel.py:65
#: ../browser/controlpanel.py:78
msgid "Moderator Email Notification"
msgstr "Varsling av moderator på epostAvisering till moderatorn med e-post"
#: ../interfaces.py:284
#: ../interfaces.py:178
msgid "Modification date"
msgstr "Ändringsdatum"
#: ../interfaces.py:254
#: ../interfaces.py:141
msgid "Name"
msgstr "Namn"
#: ../interfaces.py:278
#: ../interfaces.py:170
msgid "Notify me of new comments via email."
msgstr "Avisera mig om nya kommentarer med e-post."
@ -118,32 +144,44 @@ msgstr "Avisera mig om nya kommentarer med e-post."
msgid "Plone Discussions"
msgstr "Plone Discussions"
#: ../interfaces.py:247
#: ../interfaces.py:134
msgid "Portal type"
msgstr "Portaltyp"
#: ../browser/controlpanel.py:69
#: ../browser/controlpanel.py:82
msgid "Save"
msgstr "Spara"
#: ../interfaces.py:167
#: ../interfaces.py:46
msgid "The set of unique commentators (usernames)"
msgstr "Lista över kommentatorer (användarnamn)"
#: ../interfaces.py:156
msgid "Total number of comments on this item"
msgstr "Antal kommentarer till denna post"
#: ../interfaces.py:51
msgid "The set of unique commentators (usernames) of published_comments"
msgstr ""
#: ../browser/controlpanel.py:67
#: ../interfaces.py:35
msgid "Total number of public comments on this item"
msgstr ""
#: ../comment.py:175
msgid "Transform '%s' => '%s' not available."
msgstr ""
#: ../browser/controlpanel.py:80
msgid "User Email Notification"
msgstr "Avisering till användare med e-post"
#: ../browser/comments.py:241
#: ../interfaces.py:176
msgid "Username of the commenter"
msgstr ""
#: ../browser/comments.py:268
msgid "Your comment awaits moderator approval."
msgstr "Din kommentar inväntar moderatorns godkännande."
#. Default: "Comment"
#: ../browser/comments.py:123
#: ../browser/comments.py:138
msgid "add_comment_button"
msgstr "Kommentera"
@ -157,26 +195,57 @@ msgstr "Radera"
msgid "bulkactions_publish"
msgstr "Godkänn"
#. Default: "Cancel"
#: ../browser/comment.py:97
msgid "cancel_form_button"
msgstr ""
#. Default: "You can add a comment by filling out the form below. Plain text formatting. Web and email addresses are transformed into clickable links."
#: ../browser/comments.py:52
#: ../browser/comments.py:57
msgid "comment_description_intelligent_text"
msgstr "Du kan lägga till en kommentar genom att fylla i fälten nedan. Webbadresser och e-postadresser konverteras till klickbara länkar."
#. Default: "You can add a comment by filling out the form below. Plain text formatting. You can use the Markdown syntax for links and images."
#: ../browser/comments.py:51
msgid "comment_description_markdown"
msgstr ""
#. Default: "Comments are moderated."
#: ../browser/comments.py:58
#: ../browser/comments.py:63
msgid "comment_description_moderation_enabled"
msgstr "Kommentaren visas när den godkänts av moderatorn."
#. Default: "You can add a comment by filling out the form below. Plain text formatting."
#: ../browser/comments.py:47
#: ../browser/comments.py:46
msgid "comment_description_plain_text"
msgstr "Du kan lägga till en kommentar genom att fylla i fälten nedan."
#. Default: "${creator} on ${content}"
#: ../comment.py:46
#. Default: "Edit comment cancelled"
#: ../browser/comment.py:101
msgid "comment_edit_cancel_notification"
msgstr ""
#. Default: "Comment was edited"
#: ../browser/comment.py:91
msgid "comment_edit_notification"
msgstr ""
#. Default: "${author_name} on ${content}"
#: ../comment.py:57
#, fuzzy
msgid "comment_title"
msgstr "${creator} om ${content}"
#. Default: "Edit comment"
#: ../browser/comment.py:70
msgid "edit_comment_form_button"
msgstr ""
#. Default: "Edit comment"
#: ../browser/comment.py:54
msgid "edit_comment_form_title"
msgstr ""
#. Default: "Action"
#: ../browser/moderation.pt:85
msgid "heading_action"
@ -208,85 +277,107 @@ msgid "heading_moderate_comments"
msgstr "Moderera kommentarer"
#. Default: "If selected, anonymous users are able to post comments without loggin in. It is highly recommended to use a captcha solution to prevent spam if this setting is enabled."
#: ../interfaces.py:38
#: ../interfaces.py:216
msgid "help_anonymous_comments"
msgstr "Tillåt anonyma användare att kommentera utan att logga in. För att undvika skräppost, rekommenderas starkt att Captcha-validering aktiveras."
#. Default: "If selected, anonymous user will have to give their email."
#: ../interfaces.py:352
msgid "help_anonymous_email_enabled"
msgstr ""
#. Default: "Use this setting to enable or disable Captcha validation for comments. Install plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet, or collective.z3cform.norobots if there are no options available."
#: ../interfaces.py:82
#: ../interfaces.py:288
msgid "help_captcha"
msgstr "Aktivera captcha-validering av kommentarer. Om listrutan saknar alternativ: installera plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet eller collective.z3cform.norobots."
#. Default: "If selected, supports deleting of own comments for users with the 'Delete own comments' permission."
#: ../interfaces.py:260
msgid "help_delete_own_comment_enabled"
msgstr ""
# NOTE: "\n
# does not work.
#. Default: "Some discussion related settings are not located in the Discussion Control Panel.\nTo enable comments for a specific content type, go to the Types Control Panel of this type and choose \"Allow comments\".\nTo enable the moderation workflow for comments, go to the Types Control Panel, choose \"Comment\" and set workflow to \"Comment Review Workflow\"."
#: ../browser/controlpanel.py:33
#: ../browser/controlpanel.py:34
msgid "help_discussion_settings_editform"
msgstr "Vissa inställningar för kommentarer finns inte på denna kontrollpanel. — För att aktivera kommentarer för en viss innehållstyp, välj denna på kontrollpanelen \"Innehållstyper\" och markera rutan \"Tillåt kommentarer \". — För att aktivera ett arbetsflöde för moderation av kommentarer, välj \"Kommentar\" på kontrollpanelen \"Innehållstyper\" och sätt nytt arbetsflöde \"Comment Review Workflow\"."
#. Default: "If selected, supports editing of comments for users with the 'Edit comments' permission."
#: ../interfaces.py:249
msgid "help_edit_comment_enabled"
msgstr ""
#. Default: "If selected, users are able to post comments on the site. Though, you have to enable comments for specific content types, folders or content objects before users will be able to post comments."
#: ../interfaces.py:26
#: ../interfaces.py:202
msgid "help_globally_enabled"
msgstr "Ge användarna möjlighet att kommentera innehållsposter. Dessutom måste du aktivera kommentarer för berörda innehållstyper, mappar eller poster."
#. Default: "If selected, comments will enter a 'Pending' state in which they are invisible to the public. A user with the 'Review comments' permission ('Reviewer' or 'Manager') can approve comments to make them visible to the public. If you want to enable a custom comment workflow, you have to go to the types control panel."
#: ../interfaces.py:50
#: ../interfaces.py:232
msgid "help_moderation_enabled"
msgstr "Nya kommentarer får arbetsflödesstatus \"Pending\", och blir inte publikt tillgängliga förrän de godkänns av en moderator. Moderatorn behöver behörigheten \"Review comments\", rollerna \"Reviewer\" och \"Manager\" har det som standard. — För att ge kommentarer ett anpassat arbetsflöde, använd kontrollpanelen \"Innehållstyper\"."
#. Default: "Address to which moderator notifications will be sent."
#: ../interfaces.py:118
#: ../interfaces.py:329
msgid "help_moderator_email"
msgstr "E-postadress för aviseringar till moderatorn."
# " The moderator email address can be found in the 'Mail settings' control panel (Site 'From' address)" is FALSE!
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be found in the 'Mail settings' control panel (Site 'From' address)"
#: ../interfaces.py:107
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be set below."
#: ../interfaces.py:315
#, fuzzy
msgid "help_moderator_notification_enabled"
msgstr "Avisera moderatorn med e-post när en ny kommentar behöver åtgärdas."
#. Default: "If selected, an image of the user is shown next to the comment."
#: ../interfaces.py:97
#: ../interfaces.py:304
msgid "help_show_commenter_image"
msgstr "Visa ett porträtt av kommentatorn bredvid kommentaren."
#. Default: "Use this setting to choose if the comment text should be transformed in any way. You can choose between 'Plain text' and 'Intelligent text'. 'Intelligent text' converts plain text into HTML where line breaks and indentation is preserved, and web and email addresses are made into clickable links."
#: ../interfaces.py:66
#: ../interfaces.py:271
msgid "help_text_transform"
msgstr "\"Plain text\": Endast radbrytningar bevaras. — \"Intelligent text\": Konvertering till HTML; radbrytningar och indrag bevaras, webbadresser och e-postadresser blir klickbara länkar."
#. Default: "If selected, users can choose to be notified of new comments by email."
#: ../interfaces.py:127
#: ../interfaces.py:341
msgid "help_user_notification_enabled"
msgstr "Ge inloggade användare möjlighet att välja att bli aviserade med e-post om nya kommentarer."
#. Default: "Anonymous"
#: ../comment.py:156
#: ../browser/comments.pt:75
#: ../comment.py:193
msgid "label_anonymous"
msgstr "Anonym"
#. Default: "Enable anonymous comments"
#: ../interfaces.py:36
#: ../interfaces.py:214
msgid "label_anonymous_comments"
msgstr "Tillåt anonyma kommentarer"
#. Default: "Enable anonymous email field"
#: ../interfaces.py:350
msgid "label_anonymous_email_enabled"
msgstr ""
#. Default: "Apply"
#: ../browser/moderation.pt:71
msgid "label_apply"
msgstr "Verkställ"
#. Default: "Captcha"
#: ../interfaces.py:80
#: ../interfaces.py:286
msgid "label_captcha"
msgstr "Captcha"
#. Default: "Comment"
#: ../interfaces.py:275
#: ../interfaces.py:163
msgid "label_comment"
msgstr "Kommentar"
#. Default: "Commenting has been disabled."
#: ../browser/comments.pt:130
#: ../browser/comments.pt:163
msgid "label_commenting_disabled"
msgstr "Kommentarsfunktionen har inaktiverats."
@ -295,23 +386,33 @@ msgstr "Kommentarsfunktionen har inaktiverats."
msgid "label_delete"
msgstr "Radera"
#. Default: "Enable deleting own comments"
#: ../interfaces.py:258
msgid "label_delete_own_comment_enabled"
msgstr ""
#. Default: "Enable editing of comments"
#: ../interfaces.py:247
msgid "label_edit_comment_enabled"
msgstr ""
#. Default: "Globally enable comments"
#: ../interfaces.py:24
#: ../interfaces.py:200
msgid "label_globally_enabled"
msgstr "Aktivera kommentarer globalt"
#. Default: "Enable comment moderation"
#: ../interfaces.py:48
#: ../interfaces.py:228
msgid "label_moderation_enabled"
msgstr "Aktivera moderation för kommentarer"
#. Default: "Moderator Email Address"
#: ../interfaces.py:117
#: ../interfaces.py:325
msgid "label_moderator_email"
msgstr "Moderatorns e-postadress"
#. Default: "Enable moderator email notification"
#: ../interfaces.py:105
#: ../interfaces.py:313
msgid "label_moderator_notification_enabled"
msgstr "Aktivera avisering med e-post till moderatorn"
@ -321,12 +422,12 @@ msgid "label_publish"
msgstr "Godkänn"
#. Default: "says:"
#: ../browser/comments.pt:74
#: ../browser/comments.pt:78
msgid "label_says"
msgstr "säger:"
#. Default: "Show commenter image"
#: ../interfaces.py:95
#: ../interfaces.py:302
msgid "label_show_commenter_image"
msgstr "Visa porträtt av kommentatorn"
@ -336,22 +437,22 @@ msgid "label_show_full_comment_text"
msgstr "visa hela kommentaren"
#. Default: "Subject"
#: ../interfaces.py:271
#: ../interfaces.py:158
msgid "label_subject"
msgstr "Ämne"
#. Default: "Comment text transform"
#: ../interfaces.py:64
#: ../interfaces.py:269
msgid "label_text_transform"
msgstr "Texttransformering för kommentarer"
#. Default: "Enable user email notification"
#: ../interfaces.py:125
#: ../interfaces.py:337
msgid "label_user_notification_enabled"
msgstr "Aktivera e-post-avisering till användare"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n"
#: ../comment.py:50
#: ../comment.py:61
msgid "mail_notification_message"
msgstr ""
"En kommentar till '${title}' har postats här: ${link}\n"
@ -361,7 +462,7 @@ msgstr ""
"---\n"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n\nApprove comment:\n${link_approve}\n\nDelete comment:\n${link_delete}\n"
#: ../comment.py:58
#: ../comment.py:69
msgid "mail_notification_message_moderator"
msgstr ""
"En kommentar till '${title}' har postats här: ${link}\n"

View File

@ -1,111 +1,140 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"POT-Creation-Date: YEAR-MO-DA HO:MI +ZONE\n"
"PO-Revision-Date: \n"
"Last-Translator: Olha <olha.pelishok@gmail.com>\n"
"Last-Translator: Roman Kozlovskyi <krzroman@gmail.com>\n"
"Language-Team: Hanno Schlichting <hannosch@plone.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0\n"
"Language-Code: en\n"
"Language-Name: English\n"
"Preferred-Encodings: utf-8 latin1\n"
"Domain: DOMAIN\n"
#: ../comment.py:264
#: ../comment.py:359
msgid "A comment has been posted."
msgstr "Коментар додано."
#: ../interfaces.py:257
#: ../interfaces.py:144
msgid "A comment id unique to this conversation"
msgstr ""
msgstr "Унікальний ідентифікатор коментаря для цієї розмови"
#: ../browser/comments.py:67
#: ../browser/comments.py:72
msgid "Add a comment"
msgstr "Додати коментар"
#: ../browser/controlpanel.py:62
#: ../browser/controlpanel.py:75
msgid "Anonymous Comments"
msgstr "Анонімне коментування"
#: ../interfaces.py:282
msgid "Author name (for display)"
msgstr "Ім'я автора (яке показувати)"
#: ../browser/comments.py:248
#: ../browser/controlpanel.py:80
#: ../browser/comments.py:275
#: ../browser/controlpanel.py:93
msgid "Cancel"
msgstr "Скасувати"
#: ../browser/controlpanel.py:76
#: ../interfaces.py:184
msgid "Captcha"
msgstr ""
#: ../browser/controlpanel.py:89
msgid "Changes saved"
msgstr "Зміни збережено"
#: ../browser/moderation.py:133
#: ../browser/moderation.py:186
msgid "Comment approved."
msgstr "Коментар опубліковано."
#: ../browser/moderation.py:94
#: ../contentrules.py:92
msgid "Comment author email"
msgstr ""
#: ../contentrules.py:81
msgid "Comment author full name"
msgstr ""
#: ../contentrules.py:70
msgid "Comment author user name"
msgstr ""
#: ../browser/moderation.py:111
msgid "Comment deleted."
msgstr "Коментар знищено."
#: ../browser/controlpanel.py:63
#: ../contentrules.py:48
msgid "Comment id"
msgstr ""
#: ../contentrules.py:59
msgid "Comment text"
msgstr ""
#: ../browser/controlpanel.py:76
msgid "Commenter Image"
msgstr "Зображення коментатора"
msgid "Commenting infrastructure for Plone"
msgstr "Інфраструктура коментування в Plone"
#: ../interfaces.py:252
msgid "Conversation"
#: ../contentrules.py:47
msgid "Comments"
msgstr ""
#: ../interfaces.py:283
#: ../interfaces.py:139
msgid "Conversation"
msgstr "Розмова"
#: ../interfaces.py:177
msgid "Creation date"
msgstr "Дата створення"
#: ../interfaces.py:162
msgid "Date of the most recent comment"
msgstr "Дата останнього коментаря"
#: ../interfaces.py:41
msgid "Date of the most recent public comment"
msgstr "Дата останного публічного коментаря"
#: ../vocabularies.py:44
msgid "Disabled"
msgstr "Вимкнено"
#: ../browser/controlpanel.py:32
#: ../browser/controlpanel.py:33
msgid "Discussion settings"
msgstr "Налаштуванняя коментування"
#: ../browser/controlpanel.py:82
#: ../browser/controlpanel.py:95
msgid "Edit cancelled"
msgstr "Редагування скасовано"
#: ../interfaces.py:269
#: ../interfaces.py:156
msgid "Email"
msgstr ""
msgstr "Електронна адреса"
#: ../browser/controlpanel.py:61
#: ../browser/controlpanel.py:74
msgid "Enable Comments"
msgstr "Увімкнути можливість додавати коментарі"
#: ../interfaces.py:260
#: ../interfaces.py:147
msgid "Id of comment this comment is in reply to"
msgstr "Id коментаря, відповіддю на який - є цей коментар"
#: ../interfaces.py:274
#: ../interfaces.py:161
msgid "MIME type"
msgstr ""
msgstr "MIME-тип"
#: ../browser/controlpanel.py:65
#: ../browser/controlpanel.py:78
msgid "Moderator Email Notification"
msgstr ""
msgstr "Сповіщення модератора електронною поштою"
#: ../interfaces.py:284
#: ../interfaces.py:178
msgid "Modification date"
msgstr "Дата зміни"
#: ../interfaces.py:254
#: ../interfaces.py:141
msgid "Name"
msgstr "Ім'я"
#: ../interfaces.py:278
#: ../interfaces.py:170
msgid "Notify me of new comments via email."
msgstr "Повідомляти про нові коментарі поштою."
@ -113,32 +142,44 @@ msgstr "Повідомляти про нові коментарі поштою."
msgid "Plone Discussions"
msgstr "Коментування в Plone"
#: ../interfaces.py:247
#: ../interfaces.py:134
msgid "Portal type"
msgstr "Портал тип"
#: ../browser/controlpanel.py:69
#: ../browser/controlpanel.py:82
msgid "Save"
msgstr "Зберегти"
#: ../interfaces.py:167
#: ../interfaces.py:46
msgid "The set of unique commentators (usernames)"
msgstr "Перелік коментаторів (імена користувачів)"
#: ../interfaces.py:156
msgid "Total number of comments on this item"
msgstr "Загальна кількість коментарів до цього об'єкта"
#: ../interfaces.py:51
msgid "The set of unique commentators (usernames) of published_comments"
msgstr "Перелік коментаторів (імена користувачів) опублікованих коментарів"
#: ../browser/controlpanel.py:67
#: ../interfaces.py:35
msgid "Total number of public comments on this item"
msgstr "Загальна кількість публічних коментарів для даного елемента"
#: ../comment.py:175
msgid "Transform '%s' => '%s' not available."
msgstr "Не доступне перетворення '%s' => '%s'."
#: ../browser/controlpanel.py:80
msgid "User Email Notification"
msgstr ""
msgstr "Сповіщення користувача електронною поштою"
#: ../browser/comments.py:241
#: ../interfaces.py:176
msgid "Username of the commenter"
msgstr "Ім'я автора коментаря"
#: ../browser/comments.py:268
msgid "Your comment awaits moderator approval."
msgstr ""
msgstr "Ваш коментар очікує затвердження модератором."
#. Default: "Comment"
#: ../browser/comments.py:123
#: ../browser/comments.py:138
msgid "add_comment_button"
msgstr "Коментар"
@ -152,30 +193,60 @@ msgstr "Знищити"
msgid "bulkactions_publish"
msgstr "Опублікувати"
#. Default: "Cancel"
#: ../browser/comment.py:97
msgid "cancel_form_button"
msgstr ""
#. Default: "You can add a comment by filling out the form below. Plain text formatting. Web and email addresses are transformed into clickable links."
#: ../browser/comments.py:52
#: ../browser/comments.py:57
msgid "comment_description_intelligent_text"
msgstr "Ви можете додати коментар, заповнивши наступну форму. Просте форматування тексту. Веб адреси та адреси електронної пошти перетворюються на посилання."
#. Default: "You can add a comment by filling out the form below. Plain text formatting. You can use the Markdown syntax for links and images."
#: ../browser/comments.py:51
msgid "comment_description_markdown"
msgstr "Ви можете додати коментар, заповнивши наступну форму. Просте форматування тексту. Ви можете використовувати Markdown синтаксис для посилань і зображень."
#. Default: "Comments are moderated."
#: ../browser/comments.py:58
#: ../browser/comments.py:63
msgid "comment_description_moderation_enabled"
msgstr ""
msgstr "Коментарі модеруються."
#. Default: "You can add a comment by filling out the form below. Plain text formatting."
#: ../browser/comments.py:47
#: ../browser/comments.py:46
msgid "comment_description_plain_text"
msgstr "Ви можете додати коментар, заповнивши наступну форму. Просте форматування тексту. "
#. Default: "${creator} on ${content}"
#: ../comment.py:46
#. Default: "Edit comment cancelled"
#: ../browser/comment.py:101
msgid "comment_edit_cancel_notification"
msgstr ""
#. Default: "Comment was edited"
#: ../browser/comment.py:91
msgid "comment_edit_notification"
msgstr ""
#. Default: "${author_name} on ${content}"
#: ../comment.py:57
msgid "comment_title"
msgstr "${author_name} до ${content}"
#. Default: "Edit comment"
#: ../browser/comment.py:70
msgid "edit_comment_form_button"
msgstr ""
#. Default: "Edit comment"
#: ../browser/comment.py:54
msgid "edit_comment_form_title"
msgstr ""
#. Default: "Action"
#: ../browser/moderation.pt:85
msgid "heading_action"
msgstr ""
msgstr "Дія"
#. Default: "Comment"
#: ../browser/moderation.pt:84
@ -200,88 +271,110 @@ msgstr "У відповідь на"
#. Default: "Moderate comments"
#: ../browser/moderation.pt:24
msgid "heading_moderate_comments"
msgstr ""
msgstr "Модерування коментарів"
#. Default: "If selected, anonymous users are able to post comments without loggin in. It is highly recommended to use a captcha solution to prevent spam if this setting is enabled."
#: ../interfaces.py:38
#: ../interfaces.py:216
msgid "help_anonymous_comments"
msgstr "Якщо вибрано - то анонімні користувачі зможуть додавати коментарі без входу в систему. Для таких випадків рекомендуєтсья використовувати капчу, щоб запобігти надсиланню спаму."
#. Default: "If selected, anonymous user will have to give their email."
#: ../interfaces.py:352
msgid "help_anonymous_email_enabled"
msgstr "Якщо вибрано, анонімний користувач повинен буде вказати свою електронну пошту."
#. Default: "Use this setting to enable or disable Captcha validation for comments. Install plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet, or collective.z3cform.norobots if there are no options available."
#: ../interfaces.py:82
#: ../interfaces.py:288
msgid "help_captcha"
msgstr "Використовуйте цей параметр, щоб увімкнути або вимкнути капчу для коментарів. Для цього спершу встановіть plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet або collective.z3cform.norobots."
#. Default: "If selected, supports deleting of own comments for users with the 'Delete own comments' permission."
#: ../interfaces.py:260
msgid "help_delete_own_comment_enabled"
msgstr ""
#. Default: "Some discussion related settings are not located in the Discussion Control Panel.\nTo enable comments for a specific content type, go to the Types Control Panel of this type and choose \"Allow comments\".\nTo enable the moderation workflow for comments, go to the Types Control Panel, choose \"Comment\" and set workflow to \"Comment Review Workflow\"."
#: ../browser/controlpanel.py:33
#: ../browser/controlpanel.py:34
msgid "help_discussion_settings_editform"
msgstr ""
"Не всі налаштування коментувань знаходяться на цій сторінці.\n"
"Так, щоб увімкнути можливість коментування для певного типу вмісту, перейдіть в розділ налаштувань Типи, виберіть необхідний тип вмісту, та виберіть \"Дозволити додавати коментар\".\n"
"To enable the moderation workflow for comments, go to the Types Control Panel, choose \"Comment\" and set workflow to \"Comment Review Workflow\".\""
#. Default: "If selected, supports editing of comments for users with the 'Edit comments' permission."
#: ../interfaces.py:249
msgid "help_edit_comment_enabled"
msgstr ""
#. Default: "If selected, users are able to post comments on the site. Though, you have to enable comments for specific content types, folders or content objects before users will be able to post comments."
#: ../interfaces.py:26
#: ../interfaces.py:202
msgid "help_globally_enabled"
msgstr "Якщо вибрано, користувачі зможуть додавати коментарі на сайт. Але спочатку необхідно увімкнути можливість коментування для певних типів вмісту, тек, об'єктів."
#. Default: "If selected, comments will enter a 'Pending' state in which they are invisible to the public. A user with the 'Review comments' permission ('Reviewer' or 'Manager') can approve comments to make them visible to the public. If you want to enable a custom comment workflow, you have to go to the types control panel."
#: ../interfaces.py:50
#: ../interfaces.py:232
msgid "help_moderation_enabled"
msgstr ""
msgstr "Якщо вибрано, коментарі увійде в стан 'В очікуванні', у якому вони невидимі для громадськості. Користувач з правом 'Огляд коментарів' ('Рецензент' або 'Менеджер') може схвалити коментар, щоб зробити їх видимими для громадськості. Якщо ви хочете налаштувати робочий процес коментарів, ви повинні піти в панель керування типів."
#. Default: "Address to which moderator notifications will be sent."
#: ../interfaces.py:118
#: ../interfaces.py:329
msgid "help_moderator_email"
msgstr ""
msgstr "Адреса, за якою модератору будуть надсилатися повідомлення."
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be found in the 'Mail settings' control panel (Site 'From' address)"
#: ../interfaces.py:107
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be set below."
#: ../interfaces.py:315
#, fuzzy
msgid "help_moderator_notification_enabled"
msgstr ""
msgstr "Якщо вибрано, модератор отримує повідомлення, якщо коментар вимагає уваги. Адресу електронної пошти модератора можна знайти в 'Пошта' панелі керування (Адреса 'Від')"
#. Default: "If selected, an image of the user is shown next to the comment."
#: ../interfaces.py:97
#: ../interfaces.py:304
msgid "help_show_commenter_image"
msgstr "Якщо вибрано, зображення коментатора буде відображатись поруч з коментарем."
#. Default: "Use this setting to choose if the comment text should be transformed in any way. You can choose between 'Plain text' and 'Intelligent text'. 'Intelligent text' converts plain text into HTML where line breaks and indentation is preserved, and web and email addresses are made into clickable links."
#: ../interfaces.py:66
#: ../interfaces.py:271
msgid "help_text_transform"
msgstr ""
msgstr "Виберіть як повинен бути перетворений текст коментаря. Ви можете вибрати між 'Звичайний текст' і 'Інтелектуальні тексту'. 'Інтелектуальний текст' перетворює текст в HTML, де рядки і відступи зберігаються, інтернет адреси та адреси електронної пошти перетворяться в активні посилання."
#. Default: "If selected, users can choose to be notified of new comments by email."
#: ../interfaces.py:127
#: ../interfaces.py:341
msgid "help_user_notification_enabled"
msgstr "Якщо вибрано, користувачі зможуть обрати можливість отримувати нотифікації про нові коментарі поштою."
#. Default: "Anonymous"
#: ../comment.py:156
#: ../browser/comments.pt:75
#: ../comment.py:193
msgid "label_anonymous"
msgstr "Анонім"
#. Default: "Enable anonymous comments"
#: ../interfaces.py:36
#: ../interfaces.py:214
msgid "label_anonymous_comments"
msgstr "Увімкнути можливість анонімного коментування"
#. Default: "Enable anonymous email field"
#: ../interfaces.py:350
msgid "label_anonymous_email_enabled"
msgstr "Увімкнути поле електронної адреси для аноніма"
#. Default: "Apply"
#: ../browser/moderation.pt:71
msgid "label_apply"
msgstr "Застосувати"
#. Default: "Captcha"
#: ../interfaces.py:80
#: ../interfaces.py:286
msgid "label_captcha"
msgstr "Капча"
#. Default: "Comment"
#: ../interfaces.py:275
#: ../interfaces.py:163
msgid "label_comment"
msgstr "Коментар"
#. Default: "Commenting has been disabled."
#: ../browser/comments.pt:130
#: ../browser/comments.pt:163
msgid "label_commenting_disabled"
msgstr "Коментування вимкнено"
@ -290,25 +383,35 @@ msgstr "Коментування вимкнено"
msgid "label_delete"
msgstr "Знищити"
#. Default: "Enable deleting own comments"
#: ../interfaces.py:258
msgid "label_delete_own_comment_enabled"
msgstr ""
#. Default: "Enable editing of comments"
#: ../interfaces.py:247
msgid "label_edit_comment_enabled"
msgstr ""
#. Default: "Globally enable comments"
#: ../interfaces.py:24
#: ../interfaces.py:200
msgid "label_globally_enabled"
msgstr "Увімкнути коментування для цілого сайту"
#. Default: "Enable comment moderation"
#: ../interfaces.py:48
#: ../interfaces.py:228
msgid "label_moderation_enabled"
msgstr ""
msgstr "Увімкнути модерування коментарів"
#. Default: "Moderator Email Address"
#: ../interfaces.py:117
#: ../interfaces.py:325
msgid "label_moderator_email"
msgstr ""
msgstr "Електронна адреса модератора"
#. Default: "Enable moderator email notification"
#: ../interfaces.py:105
#: ../interfaces.py:313
msgid "label_moderator_notification_enabled"
msgstr ""
msgstr "Увімкнути сповіщення модератора"
#. Default: "Approve"
#: ../browser/moderation.pt:121
@ -316,37 +419,37 @@ msgid "label_publish"
msgstr "Опублікувати"
#. Default: "says:"
#: ../browser/comments.pt:74
#: ../browser/comments.pt:78
msgid "label_says"
msgstr ""
msgstr "каже:"
#. Default: "Show commenter image"
#: ../interfaces.py:95
#: ../interfaces.py:302
msgid "label_show_commenter_image"
msgstr "Показати зображення коментатора"
#. Default: "show full comment text"
#: ../browser/moderation.pt:114
msgid "label_show_full_comment_text"
msgstr ""
msgstr "показати повний текст коментаря"
#. Default: "Subject"
#: ../interfaces.py:271
#: ../interfaces.py:158
msgid "label_subject"
msgstr "Тема"
#. Default: "Comment text transform"
#: ../interfaces.py:64
#: ../interfaces.py:269
msgid "label_text_transform"
msgstr ""
msgstr "Перетворення тексту коментаря"
#. Default: "Enable user email notification"
#: ../interfaces.py:125
#: ../interfaces.py:337
msgid "label_user_notification_enabled"
msgstr "Увімкнути надилання нотифікації користувачу через електронну адресу"
msgstr "Увімкнути надcилання нотифікації користувачу через електронну адресу"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n"
#: ../comment.py:50
#: ../comment.py:61
msgid "mail_notification_message"
msgstr ""
"Коментар до '${title}' було додано тут: ${link}\n"
@ -356,7 +459,7 @@ msgstr ""
"---\n"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n\nApprove comment:\n${link_approve}\n\nDelete comment:\n${link_delete}\n"
#: ../comment.py:58
#: ../comment.py:69
msgid "mail_notification_message_moderator"
msgstr ""
"Коментар до '${title}' було додано тут: ${link}\n"
@ -374,20 +477,20 @@ msgstr ""
#. Default: "enable the 'Comment Review Workflow' for the Comment content type"
#: ../browser/moderation.pt:33
msgid "message_enable_comment_workflow"
msgstr ""
msgstr "увімкнути 'Робочий процес розгляду коментарів' для контент типу Коментар"
#. Default: "Moderation workflow is disabled. You have to ${enable_comment_workflow} before you can moderate comments here."
#: ../browser/moderation.pt:33
msgid "message_moderation_disabled"
msgstr ""
msgstr "Робочий процес модерування відключений. Ви повинні ${enable_comment_workflow} перш, ніж ви зможете модерувати коментарі."
#. Default: "No comments to moderate."
#: ../browser/moderation.pt:43
msgid "message_nothing_to_moderate"
msgstr ""
msgstr "Немає коментарів до модерування"
#. Default: "Bulk Actions"
#: ../browser/moderation.pt:64
msgid "title_bulkactions"
msgstr ""
msgstr "Масові Дії"

View File

@ -3,7 +3,7 @@
msgid ""
msgstr ""
"Project-Id-Version: plone.app.discussion\n"
"POT-Creation-Date: 2011-04-22 17:12+0000\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI +ZONE\n"
"PO-Revision-Date: 2011-08-19 12:23+0800\n"
"Last-Translator: Jian Aijun <jianaijun@gmail.com>\n"
"Language-Team: plone <plone-i18n@lists.sourceforge.net>\n"
@ -14,104 +14,129 @@ msgstr ""
"Language-Code: zh_CN\n"
"Language-Name: Chinese (Simplified)\n"
"Preferred-Encodings: utf-8\n"
"Domain: DOMAIN\n"
#: ../comment.py:264
#: ../comment.py:359
msgid "A comment has been posted."
msgstr "一个评论已发布。"
#: ../interfaces.py:257
#: ../interfaces.py:144
msgid "A comment id unique to this conversation"
msgstr "此对话的评论 ID"
#: ../browser/comments.py:67
#: ../browser/comments.py:72
msgid "Add a comment"
msgstr "添加​​评论"
#: ../browser/controlpanel.py:62
#: ../browser/controlpanel.py:75
msgid "Anonymous Comments"
msgstr "匿名评论"
#: ../interfaces.py:282
msgid "Author name (for display)"
msgstr "作者的名称(显示)"
#: ../browser/comments.py:248
#: ../browser/controlpanel.py:80
#: ../browser/comments.py:275
#: ../browser/controlpanel.py:93
msgid "Cancel"
msgstr "取消"
#: ../browser/controlpanel.py:76
#: ../interfaces.py:184
msgid "Captcha"
msgstr ""
#: ../browser/controlpanel.py:89
msgid "Changes saved"
msgstr "更改已保存"
#: ../browser/moderation.py:133
#: ../browser/moderation.py:186
msgid "Comment approved."
msgstr "评论已批准。"
#: ../browser/moderation.py:94
#: ../contentrules.py:92
msgid "Comment author email"
msgstr ""
#: ../contentrules.py:81
msgid "Comment author full name"
msgstr ""
#: ../contentrules.py:70
msgid "Comment author user name"
msgstr ""
#: ../browser/moderation.py:111
msgid "Comment deleted."
msgstr "评论已删除。"
#: ../browser/controlpanel.py:63
#: ../contentrules.py:48
msgid "Comment id"
msgstr ""
#: ../contentrules.py:59
msgid "Comment text"
msgstr ""
#: ../browser/controlpanel.py:76
msgid "Commenter Image"
msgstr "评论者头像"
msgid "Commenting infrastructure for Plone"
msgstr "Plone 的评论功能"
#: ../interfaces.py:252
#: ../contentrules.py:47
msgid "Comments"
msgstr ""
#: ../interfaces.py:139
msgid "Conversation"
msgstr "对话"
#: ../interfaces.py:283
#: ../interfaces.py:177
msgid "Creation date"
msgstr "创建日期"
#: ../interfaces.py:162
msgid "Date of the most recent comment"
msgstr "最近的评论日期"
#: ../interfaces.py:41
msgid "Date of the most recent public comment"
msgstr ""
#: ../vocabularies.py:44
msgid "Disabled"
msgstr "禁用"
#: ../browser/controlpanel.py:32
#: ../browser/controlpanel.py:33
msgid "Discussion settings"
msgstr "评论设置"
#: ../browser/controlpanel.py:82
#: ../browser/controlpanel.py:95
msgid "Edit cancelled"
msgstr "编辑已取消"
#: ../interfaces.py:269
#: ../interfaces.py:156
msgid "Email"
msgstr "Email"
#: ../browser/controlpanel.py:61
#: ../browser/controlpanel.py:74
msgid "Enable Comments"
msgstr "启用评论"
#: ../interfaces.py:260
#: ../interfaces.py:147
msgid "Id of comment this comment is in reply to"
msgstr "针对回复评论ID"
#: ../interfaces.py:274
#: ../interfaces.py:161
msgid "MIME type"
msgstr "MIME 类型"
#: ../browser/controlpanel.py:65
#: ../browser/controlpanel.py:78
msgid "Moderator Email Notification"
msgstr "Email 通知审核者"
#: ../interfaces.py:284
#: ../interfaces.py:178
msgid "Modification date"
msgstr "修改日期"
#: ../interfaces.py:254
#: ../interfaces.py:141
msgid "Name"
msgstr "名称"
#: ../interfaces.py:278
#: ../interfaces.py:170
msgid "Notify me of new comments via email."
msgstr "有新的评论,通过 Email 通知我"
@ -119,32 +144,44 @@ msgstr "有新的评论,通过 Email 通知我"
msgid "Plone Discussions"
msgstr "Plone 评论"
#: ../interfaces.py:247
#: ../interfaces.py:134
msgid "Portal type"
msgstr "Portal 类型"
#: ../browser/controlpanel.py:69
#: ../browser/controlpanel.py:82
msgid "Save"
msgstr "保存"
#: ../interfaces.py:167
#: ../interfaces.py:46
msgid "The set of unique commentators (usernames)"
msgstr "评论者(用户名)的集合"
#: ../interfaces.py:156
msgid "Total number of comments on this item"
msgstr "这个对话的评论总数"
#: ../interfaces.py:51
msgid "The set of unique commentators (usernames) of published_comments"
msgstr ""
#: ../browser/controlpanel.py:67
#: ../interfaces.py:35
msgid "Total number of public comments on this item"
msgstr ""
#: ../comment.py:175
msgid "Transform '%s' => '%s' not available."
msgstr ""
#: ../browser/controlpanel.py:80
msgid "User Email Notification"
msgstr "Email 通知用户"
#: ../browser/comments.py:241
#: ../interfaces.py:176
msgid "Username of the commenter"
msgstr ""
#: ../browser/comments.py:268
msgid "Your comment awaits moderator approval."
msgstr "您的评论正等待审核者的批准。"
#. Default: "Comment"
#: ../browser/comments.py:123
#: ../browser/comments.py:138
msgid "add_comment_button"
msgstr "发表评论"
@ -158,26 +195,57 @@ msgstr "删除"
msgid "bulkactions_publish"
msgstr "批准"
#. Default: "Cancel"
#: ../browser/comment.py:97
msgid "cancel_form_button"
msgstr ""
#. Default: "You can add a comment by filling out the form below. Plain text formatting. Web and email addresses are transformed into clickable links."
#: ../browser/comments.py:52
#: ../browser/comments.py:57
msgid "comment_description_intelligent_text"
msgstr "您可以通过填写以下表单发表评论,使用纯文本格式。网页和电子邮件地址将转换为可点击链接。"
#. Default: "You can add a comment by filling out the form below. Plain text formatting. You can use the Markdown syntax for links and images."
#: ../browser/comments.py:51
msgid "comment_description_markdown"
msgstr ""
#. Default: "Comments are moderated."
#: ../browser/comments.py:58
#: ../browser/comments.py:63
msgid "comment_description_moderation_enabled"
msgstr "评论将被审核。"
#. Default: "You can add a comment by filling out the form below. Plain text formatting."
#: ../browser/comments.py:47
#: ../browser/comments.py:46
msgid "comment_description_plain_text"
msgstr "您可以通过填写以下表单发表评论,使用纯文本格式。"
#. Default: "${creator} on ${content}"
#: ../comment.py:46
#. Default: "Edit comment cancelled"
#: ../browser/comment.py:101
msgid "comment_edit_cancel_notification"
msgstr ""
#. Default: "Comment was edited"
#: ../browser/comment.py:91
msgid "comment_edit_notification"
msgstr ""
#. Default: "${author_name} on ${content}"
#: ../comment.py:57
#, fuzzy
msgid "comment_title"
msgstr "${creator} 在 ${content}"
#. Default: "Edit comment"
#: ../browser/comment.py:70
msgid "edit_comment_form_button"
msgstr ""
#. Default: "Edit comment"
#: ../browser/comment.py:54
msgid "edit_comment_form_title"
msgstr ""
#. Default: "Action"
#: ../browser/moderation.pt:85
msgid "heading_action"
@ -209,85 +277,107 @@ msgid "heading_moderate_comments"
msgstr "审核评论"
#. Default: "If selected, anonymous users are able to post comments without loggin in. It is highly recommended to use a captcha solution to prevent spam if this setting is enabled."
#: ../interfaces.py:38
#: ../interfaces.py:216
msgid "help_anonymous_comments"
msgstr "如果选中,匿名用户可不登录的情况下发布评论。如果启用了此设置,强烈建议使用验证码,以防止垃圾评论。"
#. Default: "If selected, anonymous user will have to give their email."
#: ../interfaces.py:352
msgid "help_anonymous_email_enabled"
msgstr ""
#. Default: "Use this setting to enable or disable Captcha validation for comments. Install plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet, or collective.z3cform.norobots if there are no options available."
#: ../interfaces.py:82
#: ../interfaces.py:288
msgid "help_captcha"
msgstr "设置启用或禁用评论验证码功能。如果没有任何可选项可安装plone.formwidget.captchaplone.formwidget.recaptchacollective.akismet或collective.z3cform.norobots。"
#. Default: "If selected, supports deleting of own comments for users with the 'Delete own comments' permission."
#: ../interfaces.py:260
msgid "help_delete_own_comment_enabled"
msgstr ""
#. Default: "Some discussion related settings are not located in the Discussion Control Panel.\nTo enable comments for a specific content type, go to the Types Control Panel of this type and choose \"Allow comments\".\nTo enable the moderation workflow for comments, go to the Types Control Panel, choose \"Comment\" and set workflow to \"Comment Review Workflow\"."
#: ../browser/controlpanel.py:33
#: ../browser/controlpanel.py:34
msgid "help_discussion_settings_editform"
msgstr ""
"一些评论相关的设置并不位于 评论控制面板。\n"
"要启用特定内容类型的评论,请到类型控制面板,选中这种类型的 \"允许评论\"。\n"
"要启用评论审核工作流,请到类型控制面板,选择 \"评论\" 并将工作流设置为 \"评论审核工作流\"。"
#. Default: "If selected, supports editing of comments for users with the 'Edit comments' permission."
#: ../interfaces.py:249
msgid "help_edit_comment_enabled"
msgstr ""
#. Default: "If selected, users are able to post comments on the site. Though, you have to enable comments for specific content types, folders or content objects before users will be able to post comments."
#: ../interfaces.py:26
#: ../interfaces.py:202
msgid "help_globally_enabled"
msgstr "如果选中,用户可在网站上发表评论。不过,为使用户将能够发表评论,您还需要启用特定的内容类型、 文件夹或内容对象的发表评论功能。"
#. Default: "If selected, comments will enter a 'Pending' state in which they are invisible to the public. A user with the 'Review comments' permission ('Reviewer' or 'Manager') can approve comments to make them visible to the public. If you want to enable a custom comment workflow, you have to go to the types control panel."
#: ../interfaces.py:50
#: ../interfaces.py:232
msgid "help_moderation_enabled"
msgstr "如果选中,评论将进入'待审核'状态,它们对用户是看不见的。'具有审核权限的用户('审核者'或'管理者')可以批准评论,使它们对用户可见。如果你要启用定制的评论工作流,你必须到类型控制面板。"
#. Default: "Address to which moderator notifications will be sent."
#: ../interfaces.py:118
#: ../interfaces.py:329
msgid "help_moderator_email"
msgstr "审核通知发送地址。"
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be found in the 'Mail settings' control panel (Site 'From' address)"
#: ../interfaces.py:107
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be set below."
#: ../interfaces.py:315
#, fuzzy
msgid "help_moderator_notification_enabled"
msgstr "如果选中如评论需要注意审核者将被通知。审核者的Email地址可以在'邮件设置'控制面板(网站'发件人'地址)中找到。"
#. Default: "If selected, an image of the user is shown next to the comment."
#: ../interfaces.py:97
#: ../interfaces.py:304
msgid "help_show_commenter_image"
msgstr "如果选中,用户的头像显示在评论旁边。"
#. Default: "Use this setting to choose if the comment text should be transformed in any way. You can choose between 'Plain text' and 'Intelligent text'. 'Intelligent text' converts plain text into HTML where line breaks and indentation is preserved, and web and email addresses are made into clickable links."
#: ../interfaces.py:66
#: ../interfaces.py:271
msgid "help_text_transform"
msgstr "使用此设置选择评论文本的转换方式,你可以选择'纯文本'和'智能文本。'智能文本'转换纯文本成HTML格式其中换行和缩进保留Web和Email地址都转换为可点击链接。"
#. Default: "If selected, users can choose to be notified of new comments by email."
#: ../interfaces.py:127
#: ../interfaces.py:341
msgid "help_user_notification_enabled"
msgstr "如果选中用户可以选择通过Email通知新的评论。"
#. Default: "Anonymous"
#: ../comment.py:156
#: ../browser/comments.pt:75
#: ../comment.py:193
msgid "label_anonymous"
msgstr "匿名"
#. Default: "Enable anonymous comments"
#: ../interfaces.py:36
#: ../interfaces.py:214
msgid "label_anonymous_comments"
msgstr "启用匿名评论"
#. Default: "Enable anonymous email field"
#: ../interfaces.py:350
msgid "label_anonymous_email_enabled"
msgstr ""
#. Default: "Apply"
#: ../browser/moderation.pt:71
msgid "label_apply"
msgstr "应用"
#. Default: "Captcha"
#: ../interfaces.py:80
#: ../interfaces.py:286
msgid "label_captcha"
msgstr "验证码"
#. Default: "Comment"
#: ../interfaces.py:275
#: ../interfaces.py:163
msgid "label_comment"
msgstr "评论"
#. Default: "Commenting has been disabled."
#: ../browser/comments.pt:130
#: ../browser/comments.pt:163
msgid "label_commenting_disabled"
msgstr "评论已被禁用。"
@ -296,23 +386,33 @@ msgstr "评论已被禁用。"
msgid "label_delete"
msgstr "删除"
#. Default: "Enable deleting own comments"
#: ../interfaces.py:258
msgid "label_delete_own_comment_enabled"
msgstr ""
#. Default: "Enable editing of comments"
#: ../interfaces.py:247
msgid "label_edit_comment_enabled"
msgstr ""
#. Default: "Globally enable comments"
#: ../interfaces.py:24
#: ../interfaces.py:200
msgid "label_globally_enabled"
msgstr "全局启用评论"
#. Default: "Enable comment moderation"
#: ../interfaces.py:48
#: ../interfaces.py:228
msgid "label_moderation_enabled"
msgstr "启用评论审核"
#. Default: "Moderator Email Address"
#: ../interfaces.py:117
#: ../interfaces.py:325
msgid "label_moderator_email"
msgstr "审核者Email地址"
#. Default: "Enable moderator email notification"
#: ../interfaces.py:105
#: ../interfaces.py:313
msgid "label_moderator_notification_enabled"
msgstr "启用审核者Email通知"
@ -322,12 +422,12 @@ msgid "label_publish"
msgstr "批准"
#. Default: "says:"
#: ../browser/comments.pt:74
#: ../browser/comments.pt:78
msgid "label_says"
msgstr "说:"
#. Default: "Show commenter image"
#: ../interfaces.py:95
#: ../interfaces.py:302
msgid "label_show_commenter_image"
msgstr "显示评论者的头像"
@ -337,22 +437,22 @@ msgid "label_show_full_comment_text"
msgstr "显示完整的评论文本"
#. Default: "Subject"
#: ../interfaces.py:271
#: ../interfaces.py:158
msgid "label_subject"
msgstr "标题"
#. Default: "Comment text transform"
#: ../interfaces.py:64
#: ../interfaces.py:269
msgid "label_text_transform"
msgstr "评论文本转换"
#. Default: "Enable user email notification"
#: ../interfaces.py:125
#: ../interfaces.py:337
msgid "label_user_notification_enabled"
msgstr "启用用户Email通知"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n"
#: ../comment.py:50
#: ../comment.py:61
msgid "mail_notification_message"
msgstr ""
"一条评论 '${title}' 已发布在: ${link}\n"
@ -362,7 +462,7 @@ msgstr ""
"---\n"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n\nApprove comment:\n${link_approve}\n\nDelete comment:\n${link_delete}\n"
#: ../comment.py:58
#: ../comment.py:69
msgid "mail_notification_message_moderator"
msgstr ""
"一条评论 '${title}' 已发布在: ${link}\n"

View File

@ -1,8 +1,8 @@
msgid ""
msgstr ""
"Project-Id-Version: plone.app.discussion\n"
"POT-Creation-Date: 2011-04-22 17:12+0000\n"
"PO-Revision-Date: 2012-10-09 20:55+0800\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI +ZONE\n"
"PO-Revision-Date: 2014-05-02 20:55+0800\n"
"Last-Translator: TsungWei Hu <marr.tw@gmail.com>\n"
"Language-Team: Plone I18N <plone-i18n@lists.sourceforge.net>\n"
"MIME-Version: 1.0\n"
@ -14,103 +14,127 @@ msgstr ""
"Preferred-Encodings: utf-8 latin1\n"
"Domain: plone.app.discussion\n"
#: ../comment.py:264
#: ../comment.py:359
msgid "A comment has been posted."
msgstr "留言已張貼。"
#: ../interfaces.py:257
#: ../interfaces.py:144
msgid "A comment id unique to this conversation"
msgstr "留言的識別碼"
#: ../browser/comments.py:67
#: ../browser/comments.py:72
msgid "Add a comment"
msgstr "新增留言"
#: ../browser/controlpanel.py:62
#: ../browser/controlpanel.py:75
msgid "Anonymous Comments"
msgstr "匿名留言"
#: ../interfaces.py:282
msgid "Author name (for display)"
msgstr "作者 (用來顯示在網頁上)"
#: ../browser/comments.py:248
#: ../browser/controlpanel.py:80
#: ../browser/comments.py:275
#: ../browser/controlpanel.py:93
msgid "Cancel"
msgstr "取消"
#: ../browser/controlpanel.py:76
#: ../interfaces.py:184
msgid "Captcha"
msgstr ""
#: ../browser/controlpanel.py:89
msgid "Changes saved"
msgstr "變更已儲存"
#: ../browser/moderation.py:133
#: ../browser/moderation.py:186
msgid "Comment approved."
msgstr "留言已審核"
#: ../browser/moderation.py:94
#: ../contentrules.py:92
msgid "Comment author email"
msgstr "留言作者電郵"
#: ../contentrules.py:81
msgid "Comment author full name"
msgstr "留言作者姓名"
#: ../contentrules.py:70
msgid "Comment author user name"
msgstr "留言作者帳號"
#: ../browser/moderation.py:111
msgid "Comment deleted."
msgstr "留言已刪除"
#: ../browser/controlpanel.py:63
#: ../contentrules.py:48
msgid "Comment id"
msgstr "留言識別碼"
#: ../contentrules.py:59
msgid "Comment text"
msgstr "留言內文"
#: ../browser/controlpanel.py:76
msgid "Commenter Image"
msgstr "留言者圖檔"
msgid "Commenting infrastructure for Plone"
msgstr "Plone 的留言功能"
#: ../interfaces.py:252
msgid "Conversation"
msgstr "討論"
#: ../contentrules.py:47
msgid "Comments"
msgstr "留言"
#: ../interfaces.py:283
#: ../interfaces.py:139
msgid "Conversation"
msgstr "留言功能"
#: ../interfaces.py:177
msgid "Creation date"
msgstr "建立日期"
#: ../interfaces.py:162
msgid "Date of the most recent comment"
msgstr "最留言的日期"
#: ../interfaces.py:41
msgid "Date of the most recent public comment"
msgstr "最留言的日期"
#: ../vocabularies.py:44
msgid "Disabled"
msgstr "已停用"
#: ../browser/controlpanel.py:32
#: ../browser/controlpanel.py:33
msgid "Discussion settings"
msgstr "討論區設定"
#: ../browser/controlpanel.py:82
#: ../browser/controlpanel.py:95
msgid "Edit cancelled"
msgstr "取消編輯"
#: ../interfaces.py:269
#: ../interfaces.py:156
msgid "Email"
msgstr "E-Mail"
#: ../browser/controlpanel.py:61
#: ../browser/controlpanel.py:74
msgid "Enable Comments"
msgstr "允許留言"
#: ../interfaces.py:260
#: ../interfaces.py:147
msgid "Id of comment this comment is in reply to"
msgstr "留言的識別碼"
#: ../interfaces.py:274
#: ../interfaces.py:161
msgid "MIME type"
msgstr "MIME-Type"
#: ../browser/controlpanel.py:65
#: ../browser/controlpanel.py:78
msgid "Moderator Email Notification"
msgstr "審核者的電子郵件通知"
#: ../interfaces.py:284
#: ../interfaces.py:178
msgid "Modification date"
msgstr "修改日期"
#: ../interfaces.py:254
#: ../interfaces.py:141
msgid "Name"
msgstr "名稱"
#: ../interfaces.py:278
#: ../interfaces.py:170
msgid "Notify me of new comments via email."
msgstr "寄送電郵通知新留言。"
@ -118,32 +142,44 @@ msgstr "寄送電郵通知新留言。"
msgid "Plone Discussions"
msgstr "Plone 討論區"
#: ../interfaces.py:247
#: ../interfaces.py:134
msgid "Portal type"
msgstr "網站型別"
#: ../browser/controlpanel.py:69
#: ../browser/controlpanel.py:82
msgid "Save"
msgstr "儲存"
#: ../interfaces.py:167
#: ../interfaces.py:46
msgid "The set of unique commentators (usernames)"
msgstr "留言者 (使用者名稱) 的集合"
#: ../interfaces.py:156
msgid "Total number of comments on this item"
msgstr "本項目的留言數目"
#: ../interfaces.py:51
msgid "The set of unique commentators (usernames) of published_comments"
msgstr "留言的帳號列表"
#: ../browser/controlpanel.py:67
#: ../interfaces.py:35
msgid "Total number of public comments on this item"
msgstr "留言的數量統計"
#: ../comment.py:175
msgid "Transform '%s' => '%s' not available."
msgstr "轉換 '%s' => '%s' 並不存在"
#: ../browser/controlpanel.py:80
msgid "User Email Notification"
msgstr "新留言通知使用者"
#: ../browser/comments.py:241
#: ../interfaces.py:176
msgid "Username of the commenter"
msgstr "留言者的帳號"
#: ../browser/comments.py:268
msgid "Your comment awaits moderator approval."
msgstr "你的留言等待審核中。"
#. Default: "Comment"
#: ../browser/comments.py:123
#: ../browser/comments.py:138
msgid "add_comment_button"
msgstr "留言"
@ -157,25 +193,55 @@ msgstr "刪除"
msgid "bulkactions_publish"
msgstr "審核"
#. Default: "Cancel"
#: ../browser/comment.py:97
msgid "cancel_form_button"
msgstr ""
#. Default: "You can add a comment by filling out the form below. Plain text formatting. Web and email addresses are transformed into clickable links."
#: ../browser/comments.py:52
#: ../browser/comments.py:57
msgid "comment_description_intelligent_text"
msgstr "填寫下列表單後,就可以新增留言。網址會被轉換成可點選的連結。"
#. Default: "You can add a comment by filling out the form below. Plain text formatting. You can use the Markdown syntax for links and images."
#: ../browser/comments.py:51
msgid "comment_description_markdown"
msgstr "填寫表單後可以留言,可以套用 Markdown 語法來輸入連結或圖檔。"
#. Default: "Comments are moderated."
#: ../browser/comments.py:58
#: ../browser/comments.py:63
msgid "comment_description_moderation_enabled"
msgstr "留言等待審核中"
#. Default: "You can add a comment by filling out the form below. Plain text formatting."
#: ../browser/comments.py:47
#: ../browser/comments.py:46
msgid "comment_description_plain_text"
msgstr "填寫下列表單後,就可以新增留言。"
#. Default: "${creator} on ${content}"
#: ../comment.py:46
#. Default: "Edit comment cancelled"
#: ../browser/comment.py:101
msgid "comment_edit_cancel_notification"
msgstr ""
#. Default: "Comment was edited"
#: ../browser/comment.py:91
msgid "comment_edit_notification"
msgstr ""
#. Default: "${author_name} on ${content}"
#: ../comment.py:57
msgid "comment_title"
msgstr "${creator} 在 ${content} 留言"
msgstr "${author_name} 在 ${content} 留言"
#. Default: "Edit comment"
#: ../browser/comment.py:70
msgid "edit_comment_form_button"
msgstr ""
#. Default: "Edit comment"
#: ../browser/comment.py:54
msgid "edit_comment_form_title"
msgstr ""
#. Default: "Action"
#: ../browser/moderation.pt:85
@ -208,85 +274,106 @@ msgid "heading_moderate_comments"
msgstr "審核留言"
#. Default: "If selected, anonymous users are able to post comments without loggin in. It is highly recommended to use a captcha solution to prevent spam if this setting is enabled."
#: ../interfaces.py:38
#: ../interfaces.py:216
msgid "help_anonymous_comments"
msgstr "勾選的話,匿名使用者不必登入系統就能留言。建議使用 captcha 來避免垃圾留言。"
#. Default: "If selected, anonymous user will have to give their email."
#: ../interfaces.py:352
msgid "help_anonymous_email_enabled"
msgstr "勾選的話,匿名留言者必須填寫電郵信箱。"
#. Default: "Use this setting to enable or disable Captcha validation for comments. Install plone.formwidget.captcha, plone.formwidget.recaptcha, collective.akismet, or collective.z3cform.norobots if there are no options available."
#: ../interfaces.py:82
#: ../interfaces.py:288
msgid "help_captcha"
msgstr "設定留言是否啟用或停用 captcha 功能,如果還沒有這類模組選項的話,可安裝 plone.formwidget.captcha、plone.formwidget.recaptcha、collective.akismet 或 collective.z3cform.norobots。"
#. Default: "If selected, supports deleting of own comments for users with the 'Delete own comments' permission."
#: ../interfaces.py:260
msgid "help_delete_own_comment_enabled"
msgstr ""
#. Default: "Some discussion related settings are not located in the Discussion Control Panel.\nTo enable comments for a specific content type, go to the Types Control Panel of this type and choose \"Allow comments\".\nTo enable the moderation workflow for comments, go to the Types Control Panel, choose \"Comment\" and set workflow to \"Comment Review Workflow\"."
#: ../browser/controlpanel.py:33
#: ../browser/controlpanel.py:34
msgid "help_discussion_settings_editform"
msgstr ""
"某些討論區設定值並未在討論區控制面板找得到。\n"
"想要指定某個內容型別的留言功能,請到型別控制面板,指定「允許留言」。\n"
"想要指定留言的審核流程,請到型別控制面板,點選「留言」並指定工作流程為「留言審核流程」。"
#. Default: "If selected, supports editing of comments for users with the 'Edit comments' permission."
#: ../interfaces.py:249
msgid "help_edit_comment_enabled"
msgstr ""
#. Default: "If selected, users are able to post comments on the site. Though, you have to enable comments for specific content types, folders or content objects before users will be able to post comments."
#: ../interfaces.py:26
#: ../interfaces.py:202
msgid "help_globally_enabled"
msgstr "勾選的話,就啟用使用者的留言功能,不過,仍然要決定哪些內容型別、目錄、項目,能讓使用者留言。"
#. Default: "If selected, comments will enter a 'Pending' state in which they are invisible to the public. A user with the 'Review comments' permission ('Reviewer' or 'Manager') can approve comments to make them visible to the public. If you want to enable a custom comment workflow, you have to go to the types control panel."
#: ../interfaces.py:50
#: ../interfaces.py:232
msgid "help_moderation_enabled"
msgstr "勾選的話,留言會先變成待審狀態,直到通過審核後才會公開,想要客製化管理流程的話,必須到型別設定頁面。"
#. Default: "Address to which moderator notifications will be sent."
#: ../interfaces.py:118
#: ../interfaces.py:329
msgid "help_moderator_email"
msgstr "審核通知信的寄送地址。"
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be found in the 'Mail settings' control panel (Site 'From' address)"
#: ../interfaces.py:107
#. Default: "If selected, the moderator is notified if a comment needs attention. The moderator email address can be set below."
#: ../interfaces.py:315
msgid "help_moderator_notification_enabled"
msgstr "勾選的話,有人留言時就會通知審核者。審核者的寄信地址記錄在郵件設定頁面裡。"
msgstr "勾選的話,有人留言時就會通知審核者。審核者的寄信地址可在下列欄位設定。"
#. Default: "If selected, an image of the user is shown next to the comment."
#: ../interfaces.py:97
#: ../interfaces.py:304
msgid "help_show_commenter_image"
msgstr "勾選的話,使用者的圖檔會顯示在留言旁邊。"
#. Default: "Use this setting to choose if the comment text should be transformed in any way. You can choose between 'Plain text' and 'Intelligent text'. 'Intelligent text' converts plain text into HTML where line breaks and indentation is preserved, and web and email addresses are made into clickable links."
#: ../interfaces.py:66
#: ../interfaces.py:271
msgid "help_text_transform"
msgstr "選擇留言的標註格式,選擇「排版文字」的話,會主動保留內容的換行和縮排,也會把網址變成可以點選的連結。"
#. Default: "If selected, users can choose to be notified of new comments by email."
#: ../interfaces.py:127
#: ../interfaces.py:341
msgid "help_user_notification_enabled"
msgstr "勾選的話,使用者可以收到新留言的通知信。"
#. Default: "Anonymous"
#: ../comment.py:156
#: ../browser/comments.pt:75
#: ../comment.py:193
msgid "label_anonymous"
msgstr "無名氏"
#. Default: "Enable anonymous comments"
#: ../interfaces.py:36
#: ../interfaces.py:214
msgid "label_anonymous_comments"
msgstr "啟用匿名留言功能"
#. Default: "Enable anonymous email field"
#: ../interfaces.py:350
msgid "label_anonymous_email_enabled"
msgstr "啟用匿名留言的電郵欄位"
#. Default: "Apply"
#: ../browser/moderation.pt:71
msgid "label_apply"
msgstr "更新"
#. Default: "Captcha"
#: ../interfaces.py:80
#: ../interfaces.py:286
msgid "label_captcha"
msgstr "captcha"
#. Default: "Comment"
#: ../interfaces.py:275
#: ../interfaces.py:163
msgid "label_comment"
msgstr "留言"
#. Default: "Commenting has been disabled."
#: ../browser/comments.pt:130
#: ../browser/comments.pt:163
msgid "label_commenting_disabled"
msgstr "留言功能已停用。"
@ -295,23 +382,33 @@ msgstr "留言功能已停用。"
msgid "label_delete"
msgstr "刪除"
#. Default: "Enable deleting own comments"
#: ../interfaces.py:258
msgid "label_delete_own_comment_enabled"
msgstr ""
#. Default: "Enable editing of comments"
#: ../interfaces.py:247
msgid "label_edit_comment_enabled"
msgstr ""
#. Default: "Globally enable comments"
#: ../interfaces.py:24
#: ../interfaces.py:200
msgid "label_globally_enabled"
msgstr "全域啟用留言功能"
#. Default: "Enable comment moderation"
#: ../interfaces.py:48
#: ../interfaces.py:228
msgid "label_moderation_enabled"
msgstr "啟用審核功能"
#. Default: "Moderator Email Address"
#: ../interfaces.py:117
#: ../interfaces.py:325
msgid "label_moderator_email"
msgstr "審核者電郵地址"
#. Default: "Enable moderator email notification"
#: ../interfaces.py:105
#: ../interfaces.py:313
msgid "label_moderator_notification_enabled"
msgstr "啟用通知審核者的功能"
@ -321,12 +418,12 @@ msgid "label_publish"
msgstr "審核"
#. Default: "says:"
#: ../browser/comments.pt:74
#: ../browser/comments.pt:78
msgid "label_says"
msgstr "留言:"
#. Default: "Show commenter image"
#: ../interfaces.py:95
#: ../interfaces.py:302
msgid "label_show_commenter_image"
msgstr "顯示留言者圖檔"
@ -336,29 +433,45 @@ msgid "label_show_full_comment_text"
msgstr "顯示完整的留言內容"
#. Default: "Subject"
#: ../interfaces.py:271
#: ../interfaces.py:158
msgid "label_subject"
msgstr "標題"
#. Default: "Comment text transform"
#: ../interfaces.py:64
#: ../interfaces.py:269
msgid "label_text_transform"
msgstr "留言排版格式"
#. Default: "Enable user email notification"
#: ../interfaces.py:125
#: ../interfaces.py:337
msgid "label_user_notification_enabled"
msgstr "啟用通知使用者的功能"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n"
#: ../comment.py:50
#: ../comment.py:61
msgid "mail_notification_message"
msgstr "${title} 有新留言:${link}\n\n---\n${text}\n---\n"
msgstr ""
"${title} 有新留言:${link}\n"
"\n"
"---\n"
"${text}\n"
"---\n"
#. Default: "A comment on '${title}' has been posted here: ${link}\n\n---\n${text}\n---\n\nApprove comment:\n${link_approve}\n\nDelete comment:\n${link_delete}\n"
#: ../comment.py:58
#: ../comment.py:69
msgid "mail_notification_message_moderator"
msgstr "${title} 有新留言:${link}\n\n---\n${text}\n---\n\n審核通過\n${link_approve}\n\n刪除留言\n${link_delete}\n"
msgstr ""
"${title} 有新留言:${link}\n"
"\n"
"---\n"
"${text}\n"
"---\n"
"\n"
"審核通過:\n"
"${link_approve}\n"
"\n"
"刪除留言:\n"
"${link_delete}\n"
#. Default: "enable the 'Comment Review Workflow' for the Comment content type"
#: ../browser/moderation.pt:33

View File

@ -1,4 +1,4 @@
from zope.component import queryUtility
from Products.CMFCore.utils import getToolByName
from Acquisition import aq_inner, aq_parent
@ -8,7 +8,6 @@ from Products.CMFPlone.utils import base_hasattr
from Products.CMFPlone.utils import safe_callable
from plone.app.discussion.conversation import ANNOTATION_KEY
from plone.app.discussion.interfaces import ICommentingTool
def patchedClearFindAndRebuild(self):
@ -26,14 +25,14 @@ def patchedClearFindAndRebuild(self):
obj.indexObject()
annotions = IAnnotations(obj)
ctool = queryUtility(ICommentingTool)
catalog = getToolByName(obj, "portal_catalog")
if ANNOTATION_KEY in annotions:
conversation = annotions[ANNOTATION_KEY]
conversation = conversation.__of__(obj)
for comment in conversation.getComments():
try:
if ctool:
ctool.indexObject(comment)
if catalog:
catalog.indexObject(comment)
except StopIteration: # pragma: no cover
pass

View File

@ -9,4 +9,19 @@
title="Review comments"
/>
<permission
id="plone.app.discussion.EditComments"
title="Edit comments"
/>
<permission
id="plone.app.discussion.DeleteOwnComments"
title="Delete own comments"
/>
<permission
id="plone.app.discussion.DeleteComments"
title="Delete comments"
/>
</configure>

View File

@ -1,9 +0,0 @@
<?xml version="1.0"?>
<componentregistry>
<utilities>
<utility
interface="plone.app.discussion.interfaces.ICommentingTool"
object="portal_discussion"
/>
</utilities>
</componentregistry>

View File

@ -12,7 +12,7 @@
category="Plone"
condition_expr=""
icon_expr="string:${portal_url}/discussionitem_icon.png"
url_expr="string:${portal_url}/@@discussion-settings"
url_expr="string:${portal_url}/@@discussion-controlpanel"
visible="True"
i18n:attributes="title">
<permission>Manage portal</permission>

View File

@ -1,5 +1,5 @@
<metadata>
<version>100</version>
<version>102</version>
<dependencies>
<dependency>profile-plone.app.registry:default</dependency>
</dependencies>

View File

@ -1,4 +1,7 @@
<?xml version="1.0"?>
<registry>
<records interface="plone.app.discussion.interfaces.IDiscussionSettings" />
<records interface="plone.app.discussion.interfaces.IDiscussionSettings">
<value key="edit_comment_enabled">False</value>
<value key="delete_own_comment_enabled">False</value>
</records>
</registry>

View File

@ -6,8 +6,25 @@
<role name="Site Administrator"/>
<role name="Reviewer"/>
</permission>
<permission name="Edit comments" acquire="True">
<role name="Manager"/>
<role name="Site Administrator"/>
<role name="Reviewer"/>
<role name="Owner"/>
</permission>
<permission name="Delete comments" acquire="True">
<role name="Manager"/>
<role name="Site Administrator"/>
<role name="Reviewer"/>
</permission>
<permission name="Reply to item" acquire="False">
<role name="Authenticated"/>
</permission>
<permission name="Delete own comments" acquire="False">
<role name="Manager"/>
<role name="Site Administrator"/>
<role name="Reviewer"/>
<role name="Owner"/>
</permission>
</permissions>
</rolemap>

View File

@ -1,5 +0,0 @@
<?xml version="1.0"?>
<tool-setup>
<required tool_id="portal_discussion"
class="plone.app.discussion.tool.CommentingTool"/>
</tool-setup>

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<object name="portal_workflow">
<object name="portal_workflow" meta_type="Plone Workflow Tool">
<object name="comment_review_workflow" meta_type="Workflow"/>
<bindings>
<type type_id="Discussion Item">

View File

@ -0,0 +1,15 @@
from Products.CMFCore.utils import getToolByName
def index_object(obj, event):
"""Index the object when it is added to the conversation.
"""
catalog = getToolByName(obj, 'portal_catalog')
return catalog.reindexObject(obj)
def unindex_object(obj, event):
"""Unindex the object when it is removed from the conversation.
"""
catalog = getToolByName(obj, 'portal_catalog')
return catalog.unindexObject(obj)

View File

@ -15,22 +15,34 @@
handler=".comment.notify_content_object"
/>
<subscriber
for="plone.app.discussion.interfaces.IComment
zope.lifecycleevent.interfaces.IObjectAddedEvent"
handler=".comment.notify_comment_added"
/>
<subscriber
for="plone.app.discussion.interfaces.IComment
zope.lifecycleevent.interfaces.IObjectRemovedEvent"
handler=".comment.notify_content_object"
/>
<subscriber
for="plone.app.discussion.interfaces.IComment
zope.lifecycleevent.interfaces.IObjectRemovedEvent"
handler=".comment.notify_comment_removed"
/>
<subscriber
for="plone.app.discussion.interfaces.IComment
zope.lifecycleevent.interfaces.IObjectAddedEvent"
handler=".tool.index_object"
handler=".subscribers.index_object"
/>
<subscriber
for="plone.app.discussion.interfaces.IComment
zope.lifecycleevent.interfaces.IObjectRemovedEvent"
handler=".tool.unindex_object"
handler=".subscribers.unindex_object"
/>
<subscriber

View File

@ -1,15 +1,19 @@
from Products.CMFCore.utils import getToolByName
from plone.app.testing import PloneSandboxLayer
from plone.app.contenttypes.testing import PLONE_APP_CONTENTTYPES_FIXTURE
from plone.app.discussion.interfaces import IDiscussionSettings
from plone.app.robotframework.testing import REMOTE_LIBRARY_ROBOT_TESTING
from plone.app.testing import applyProfile
from plone.app.testing import PLONE_FIXTURE
from plone.app.testing import IntegrationTesting
from plone.app.testing import FunctionalTesting
from plone.app.testing import IntegrationTesting
from plone.app.testing import PloneSandboxLayer
from plone.app.testing import setRoles
from plone.app.testing import TEST_USER_ID
from plone.registry.interfaces import IRegistry
from Products.CMFCore.utils import getToolByName
from zope.component import queryUtility
from zope.configuration import xmlconfig
try:
import plone.app.collection
import plone.app.collection # noqa
COLLECTION_TYPE = "Collection"
except:
COLLECTION_TYPE = "Topic"
@ -17,7 +21,7 @@ except:
class PloneAppDiscussion(PloneSandboxLayer):
defaultBases = (PLONE_FIXTURE,)
defaultBases = (PLONE_APP_CONTENTTYPES_FIXTURE,)
USER_NAME = 'johndoe'
USER_PASSWORD = 'secret'
@ -28,6 +32,8 @@ class PloneAppDiscussion(PloneSandboxLayer):
USER_WITH_FULLNAME_PASSWORD = 'secret'
MANAGER_USER_NAME = 'manager'
MANAGER_USER_PASSWORD = 'secret'
REVIEWER_NAME = 'reviewer'
REVIEWER_PASSWORD = 'secret'
def setUpZope(self, app, configurationContext):
# Load ZCML
@ -60,7 +66,15 @@ class PloneAppDiscussion(PloneSandboxLayer):
['Member'],
[],
)
acl_users.userFolderAddUser(
self.REVIEWER_NAME,
self.REVIEWER_PASSWORD,
['Member'],
[],
)
mtool = getToolByName(portal, 'portal_membership', None)
gtool = getToolByName(portal, 'portal_groups', None)
gtool.addPrincipalToGroup(self.REVIEWER_NAME, 'Reviewers')
mtool.addMember('jim', 'Jim', ['Member'], [])
mtool.getMemberById('jim').setMemberProperties(
{"fullname": 'Jim Fult\xc3\xb8rn'})
@ -72,6 +86,24 @@ class PloneAppDiscussion(PloneSandboxLayer):
[],
)
# Add a document
setRoles(portal, TEST_USER_ID, ['Manager'])
portal.invokeFactory(
id='doc1',
title='Document 1',
type_name='Document'
)
class PloneAppDiscussionRobot(PloneAppDiscussion):
def setUpPloneSite(self, portal):
registry = queryUtility(IRegistry)
settings = registry.forInterface(IDiscussionSettings)
settings.globally_enabled = True
PLONE_APP_DISCUSSION_ROBOT_FIXTURE = PloneAppDiscussionRobot()
PLONE_APP_DISCUSSION_FIXTURE = PloneAppDiscussion()
PLONE_APP_DISCUSSION_INTEGRATION_TESTING = IntegrationTesting(
bases=(PLONE_APP_DISCUSSION_FIXTURE,),
@ -79,3 +111,10 @@ PLONE_APP_DISCUSSION_INTEGRATION_TESTING = IntegrationTesting(
PLONE_APP_DISCUSSION_FUNCTIONAL_TESTING = FunctionalTesting(
bases=(PLONE_APP_DISCUSSION_FIXTURE,),
name="PloneAppDiscussion:Functional")
PLONE_APP_DISCUSSION_ROBOT_TESTING = FunctionalTesting(
bases=(
PLONE_APP_DISCUSSION_ROBOT_FIXTURE,
REMOTE_LIBRARY_ROBOT_TESTING
),
name="PloneAppDiscussion:Robot"
)

View File

@ -0,0 +1,93 @@
XXX: This functional test part has been removed due to the removal of
ATContentTypes from PLONE_FIXTURE. We have to rewrite this test as a robot
test because the dexterity collections do not work without js.
List comments in a collection
-----------------------------
Create a collection.
>>> from plone.app.testing import setRoles
>>> from plone.app.testing import TEST_USER_NAME
>>> setRoles(portal, 'manager', ['Manager'])
>>> browser.open(portal.absolute_url())
>>> from plone.app.discussion.testing import COLLECTION_TYPE
>>> browser.getLink(url='++add++' + COLLECTION_TYPE).click()
>>> open('/tmp/testbrowser.html', 'w').write(browser.contents)
>>> import pdb; pdb.set_trace()
>>> browser.getControl('form.widgets.IDublinCore.title').value = 'Foo Comment Collection'
>>> browser.getControl('Save').click()
>>> print browser.contents
<...Changes saved...
>>> topic_url = browser.url
Set the collection criteria.
>>> browser.open(topic_url + "/edit")
>>> if COLLECTION_TYPE == "Collection":
... browser.getControl(name="addindex").value = ['portal_type']
... browser.getControl(name="form.button.addcriteria").click()
... browser.getControl(name="addoperator").value = ['plone.app.querystring.operation.selection.is']
... browser.getControl(name="form.button.addcriteria").click()
... browser.getControl(name="query.v:records:list").value = ["Discussion Item"]
... browser.getControl(name="form.button.save").click()
... else:
... browser.getLink('Criteria').click()
... browser.getControl('Item Type', index=0).selected = True
... browser.getControl('Select content types').selected = True
... browser.getControl('Add criteria').click()
... browser.getControl('Comment').selected = True
... browser.getControl('Save', index=0).click()
>>> print browser.contents
<...Changes saved...
View the collection listing.
>>> browser.getLink('View').click()
>>> browser.getLink('admin on Doc1', index=0)
<Link text='admin on Doc1' url='http://nohost/plone/doc1/++conversation++default/...'>
>>> browser.getLink('admin on Doc1', index=1)
<Link text='admin on Doc1' url='http://nohost/plone/doc1/++conversation++default/...'>
>>> browser.getLink('Anonymous on Doc1', index=0)
<Link text='Anonymous on Doc1' url='http://nohost/plone/doc1/++conversation++default/...'>
>>> browser.getLink('Anonymous on Doc1', index=1)
<Link text='Anonymous on Doc1' url='http://nohost/plone/doc1/++conversation++default/...'>
>>> browser.getLink(tarek_fullname + ' on Doc1')
<Link text='Tarek Ziad\xc3\xa9 on Doc1' url='http://nohost/plone/doc1/++conversation++default/...'>
>>> browser.getLink(jim_fullname + ' on Doc1')
<Link text='Jim Fult\xc3\xb8rn on Doc1' url='http://nohost/plone/doc1/++conversation++default/...'>
Comments are unindexed when the content is deleted
--------------------------------------------------
Delete the commented content.
>>> browser.open(urldoc1)
>>> browser.getLink('Delete').click()
>>> browser.getControl('Delete').click()
>>> print browser.contents
<...Doc1 has been deleted...
The comments are no longer in the catalog.
>>> browser.open(topic_url)
>>> browser.getLink('admin on Doc1', index=0)
Traceback (most recent call last):
LinkNotFoundError
>>> browser.getLink('admin on Doc1', index=1)
Traceback (most recent call last):
LinkNotFoundError
>>> browser.getLink('Anonymous on Doc1', index=0)
Traceback (most recent call last):
LinkNotFoundError
>>> browser.getLink('Anonymous on Doc1', index=1)
Traceback (most recent call last):
LinkNotFoundError
>>> browser.getLink(tarek_fullname + ' on Doc1')
Traceback (most recent call last):
LinkNotFoundError
>>> browser.getLink(jim_fullname + ' on Doc1')
Traceback (most recent call last):
LinkNotFoundError

View File

@ -33,6 +33,7 @@ We also keep another testbrowser handy for testing how tiles are rendered if
you're not logged in::
>>> unprivileged_browser = Browser(app)
>>> unprivileged_browser.handleErrors = False
Enable commenting.
@ -60,23 +61,29 @@ We need to commit the transaction, otherwise setting the workflow will not work.
Enable anonymous comments
>>> browser.open(portal_url+'/@@discussion-settings')
>>> browser.getControl(name='form.widgets.anonymous_comments:list').value = [True]
>>> browser.open(portal_url+'/@@discussion-controlpanel')
>>> browser.getControl(name='form.widgets.anonymous_comments:list').value = True
>>> browser.getControl(name='form.buttons.save').click()
Create a public page with comments allowed.
>>> browser.open(portal_url)
>>> browser.getLink(id='document').click()
>>> browser.getControl(name='title').value = "Doc"
>>> browser.getControl(name='allowDiscussion:boolean').value = True
>>> browser.getControl(name='form.button.save').click()
>>> browser.getControl(name='form.widgets.IDublinCore.title').value = "Doc"
>>> browser.getControl(name='form.widgets.IAllowDiscussion.allow_discussion:list').value = ['True']
>>> browser.getControl('Save').click()
>>> urldoc = browser.url
Check that the form has been properly submitted
>>> browser.url
'http://nohost/plone/doc'
'http://nohost/plone/doc/view'
Make sure the document is published:
>>> browser.getLink("Publish").click()
>>> 'Published' in browser.contents
True
Post some comments as anonymous user:
@ -124,6 +131,11 @@ Anonymous user can not see any posts or comment actions
>>> 'form.button.PublishComment' in unprivileged_browser.contents
False
The catalog does not list the comments yet:
>>> portal.portal_catalog.searchResults(id='doc', total_comments=0)
[<Products...]
Users with 'Review comment' permission can see unapproved comments and comment
actions.
@ -176,6 +188,11 @@ Make sure anonyous users see the approved comment, but not the unapproved ones.
>>> 'First anonymous comment' in unprivileged_browser.contents
True
Make sure the catalog only lists the public comments.
>>> portal.portal_catalog.searchResults(id='doc', total_comments=1)
[<Products...]
Delete a comment in the comments view
-------------------------------------
@ -205,4 +222,11 @@ Make sure the second comment has been deleted.
>>> 'Second anonymous comment' in browser.contents
False
Delete the first, published comment.
>>> browser.open(urldoc)
>>> browser.getControl('Delete', index=0).click()
Make sure the catalog has been updated properly.
>>> portal.portal_catalog.searchResults(id='doc', total_comments=0)
[<Products...]

View File

@ -30,6 +30,9 @@ We also keep another testbrowser handy for testing how tiles are rendered if
you're not logged in::
>>> unprivileged_browser = Browser(app)
>>> browser_member = Browser(app)
>>> browser_user = Browser(app)
>>> browser_reviewer = Browser(app)
Make sure we have a test user from the layer and it uses fancy characters:
@ -53,13 +56,18 @@ Enable commenting.
Create a public page with comments allowed.
>>> browser.open(portal_url)
>>> browser.getLink(id='document').click()
>>> browser.getControl(name='title').value = "Doc1"
>>> browser.getControl(name='allowDiscussion:boolean').value = True
>>> browser.getControl(name='form.button.save').click()
>>> browser.open(portal['doc1'].absolute_url() + '/edit')
>>> browser.getControl(name='form.widgets.IDublinCore.title').value = "Doc1"
>>> browser.getControl(name='form.widgets.IAllowDiscussion.allow_discussion:list').value = ['True']
>>> browser.getControl('Save').click()
>>> urldoc1 = browser.url
Make sure the document is published:
>>> browser.getLink("Publish").click()
>>> 'Published' in browser.contents
True
Check that the form has been properly submitted
>>> browser.url
@ -115,20 +123,19 @@ Post a comment as user
Login as user (without the 'Member' role).
>>> browser.open(portal_url + '/logout')
>>> browser.open(portal_url + '/login_form')
>>> browser.getControl(name='__ac_name').value = 'johndoe'
>>> browser.getControl(name='__ac_password').value = 'secret'
>>> browser.getControl(name='submit').click()
>>> browser_user.open(portal_url + '/login_form')
>>> browser_user.getControl(name='__ac_name').value = 'johndoe'
>>> browser_user.getControl(name='__ac_password').value = 'secret'
>>> browser_user.getControl(name='submit').click()
Users without the 'Reply to item' permission will not see the comment form,
because they don't have the 'Reply to item' permission. By default, this
permission is only granted to the 'Member' role.
>>> 'form.widgets.text' in browser.contents
>>> 'form.widgets.text' in browser_user.contents
False
>>> 'form.buttons.comment' in browser.contents
>>> 'form.buttons.comment' in browser_user.contents
False
@ -136,26 +143,24 @@ Post a comment as member
------------------------
Login as user 'jim'.
>>> browser.open(portal_url + '/logout')
>>> browser.open(portal_url + '/login_form')
>>> browser.getControl(name='__ac_name').value = 'jim'
>>> browser.getControl(name='__ac_password').value = 'secret'
>>> browser.getControl(name='submit').click()
>>> browser_member.open(portal_url + '/login_form')
>>> browser_member.getControl(name='__ac_name').value = 'jim'
>>> browser_member.getControl(name='__ac_password').value = 'secret'
>>> browser_member.getControl(name='submit').click()
Post a comment as user jim.
>>> browser.open(urldoc1)
>>> browser.getControl(name='form.widgets.text').value = "Comment from Jim"
>>> submit = browser.getControl(name='form.buttons.comment')
>>> browser_member.open(urldoc1)
>>> browser_member.getControl(name='form.widgets.text').value = "Comment from Jim"
>>> submit = browser_member.getControl(name='form.buttons.comment')
>>> submit.click()
Check if the comment has been added properly.
>>> browser.contents
>>> browser_member.contents
'...<a href="http://nohost/plone/author/jim">Jim Fult\xc3\xb8rn</a>...says:...'
>>> "Comment from Jim" in browser.contents
>>> "Comment from Jim" in browser_member.contents
True
@ -176,7 +181,7 @@ Enable anonymous comment
>>> browser.getControl(name='__ac_name').value = 'admin'
>>> browser.getControl(name='__ac_password').value = 'secret'
>>> browser.getControl(name='submit').click()
>>> browser.open(portal_url+'/@@discussion-settings')
>>> browser.open(portal_url+'/@@discussion-controlpanel')
>>> browser.getControl(name='form.widgets.anonymous_comments:list').value = [True]
>>> browser.getControl(name='form.buttons.save').click()
>>> browser.open(portal_url + '/logout')
@ -227,7 +232,7 @@ Find a comment id to reply to.
>>> browser.open(urldoc1)
>>> import re
>>> comment_div = re.findall('<div.*?.class="comment.*?>', browser.contents)[0]
>>> id = re.findall('"([^"]*)"', comment_div)[2]
>>> id = re.findall('"([^"]*)"', comment_div)[1]
Post a reply to an existing comment.
@ -244,6 +249,173 @@ Check that the reply has been posted properly.
True
Edit an existing comment
------------------------
Log in as admin
>>> browser.getLink('Log out').click()
>>> browser.open(portal_url + '/login_form')
>>> browser.getControl('Login Name').value = 'admin'
>>> browser.getControl('Password').value = 'secret'
>>> browser.getControl('Log in').click()
Use the Plone control panel to enable comment editing.
>>> browser.open(portal_url + '/plone_control_panel')
>>> browser.getLink('Discussion').click()
>>> browser.getControl('Enable editing of comments').selected = True
>>> browser.getControl(name='form.buttons.save').click()
Extract the edit comment url from the first "edit comment" button
>>> browser.open(urldoc1)
>>> form = browser.getForm(name='edit', index=0)
>>> '@@edit-comment' in form.action
True
Open the edit comment view
>>> browser.open(form.action)
>>> ctrl = browser.getControl('Comment')
>>> ctrl.value
'Comment from admin'
Change and save the comment
>>> ctrl.value = 'Comment from admin / was edited'
>>> browser.getControl('Edit comment').click()
This used to trigger permissions problems in some portlet configurations.
Check it ain't so.
>>> 'require_login' in browser.url
False
>>> browser.url.startswith('http://nohost/plone/doc1')
True
>>> 'Comment from admin / was edited' in browser.contents
True
Opening the edit comment view, then cancel, does nothing.
>>> form = browser.getForm(name='edit', index=0)
>>> '@@edit-comment' in form.action
True
>>> browser.open(form.action)
>>> browser.getControl('Cancel').click()
>>> browser.url.startswith('http://nohost/plone/doc1')
True
Anon cannot edit comments.
>>> unprivileged_browser.open(urldoc1)
>>> '@@edit-comments' in browser.contents
False
But Anon can see the edited comment.
>>> 'Comment from admin / was edited' in unprivileged_browser.contents
True
Deleting existing comments | 'Delete comments' permission
----------------------------------------------------------
Anonymous cannot delete comments
>>> unprivileged_browser.open(urldoc1)
>>> 'form.button.Delete' in unprivileged_browser.contents
False
A member cannot delete his own comments if he can't review or he isn't a Site Administrator
>>> browser_member.open(urldoc1)
>>> 'form.button.Delete' in browser_member.contents
False
Admin can delete comments
>>> browser.open(urldoc1)
>>> 'form.button.Delete' in browser.contents
True
Extract the delete comment url from the first "delete comment" button
>>> browser.open(urldoc1)
>>> form = browser.getForm(name='delete', index=0)
>>> delete_url = form.action
>>> '@@moderate-delete-comment' in delete_url
True
>>> comment_id = delete_url.split('/')[-2]
Anonymous cannot delete a comment by hitting the delete url directly.
>>> unprivileged_browser.open(delete_url)
The comment is still there
>>> unprivileged_browser.open(urldoc1)
>>> comment_id in unprivileged_browser.contents
True
A Member cannot delete even his own comment by hitting the delete url directly.
Extract the member comment id from the admin browser
>>> form = browser.getForm(name='delete', index=2)
>>> delete_url = form.action
>>> '@@moderate-delete-comment' in delete_url
True
>>> comment_id = delete_url.split('/')[-2]
Now try to hit that url as the member owning that comment.
Work around some possible testbrowser breakage and check the result later.
>>> try:
... browser_member.open(delete_url)
... except:
... pass
The comment is still there
>>> browser_member.open(urldoc1)
>>> comment_id in browser_member.contents
True
>>> 'Comment from Jim' in browser_member.contents
True
Now login as user 'reviewer'
>>> browser_reviewer.open(portal_url + '/login_form')
>>> browser_reviewer.getControl(name='__ac_name').value = 'reviewer'
>>> browser_reviewer.getControl(name='__ac_password').value = 'secret'
>>> browser_reviewer.getControl(name='submit').click()
Admin and who have 'Delete comments' permission (reviewers for example), can delete comments
>>> browser_reviewer.open(urldoc1)
>>> form = browser_reviewer.getForm(name='delete', index=0)
>>> '@@moderate-delete-comment' in form.action
True
>>> comment_id = form.action.split('/')[-2]
Submitting the form runs into a testbrowser notFoundException.
We'll just catch that and check the result later.
>>> try:
... form.submit()
... except:
... pass
Returning to the document we find the deleted comment is indeed gone
>>> browser_reviewer.open(urldoc1)
>>> comment_id in browser_reviewer.contents
False
Post a comment with comment review workflow enabled
---------------------------------------------------
@ -285,7 +457,6 @@ This is a regression test for http://dev.plone.org/plone/ticket/11157
Login as admin.
>>> browser.open(portal_url + '/logout')
>>> browser.open(portal_url + '/login_form')
>>> browser.getControl(name='__ac_name').value = 'admin'
>>> browser.getControl(name='__ac_password').value = 'secret'
@ -293,101 +464,11 @@ Login as admin.
Edit the content object.
>>> browser.open(urldoc1 + "/edit")
>>> browser.getControl(name='text').value = "Lorem ipsum"
>>> browser.getControl(name='form.button.save').click()
>>> browser.open("http://nohost/plone/doc1/edit")
>>> browser.getControl(name='form.widgets.IRichText.text').value = "Lorem ipsum"
>>> browser.getControl('Save').click()
Make sure the edit was successful.
>>> 'Lorem ipsum' in browser.contents
True
List comments in a collection
-----------------------------
Create a collection.
>>> from plone.app.testing import setRoles
>>> from plone.app.testing import TEST_USER_NAME
>>> setRoles(portal, 'manager', ['Manager'])
>>> browser.open(portal.absolute_url())
>>> from plone.app.discussion.testing import COLLECTION_TYPE
>>> browser.getLink(url='createObject?type_name=' + COLLECTION_TYPE).click()
>>> browser.getControl('Title', index=0
... ).value = 'Foo Comment Collection'
>>> browser.getControl('Save').click()
>>> print browser.contents
<...Changes saved...
>>> topic_url = browser.url
Set the collection criteria.
>>> browser.open(topic_url + "/edit")
>>> if COLLECTION_TYPE == "Collection":
... browser.getControl(name="addindex").value = ['portal_type']
... browser.getControl(name="form.button.addcriteria").click()
... browser.getControl(name="addoperator").value = ['plone.app.querystring.operation.selection.is']
... browser.getControl(name="form.button.addcriteria").click()
... browser.getControl(name="query.v:records:list").value = ["Discussion Item"]
... browser.getControl(name="form.button.save").click()
... else:
... browser.getLink('Criteria').click()
... browser.getControl('Item Type', index=0).selected = True
... browser.getControl('Select content types').selected = True
... browser.getControl('Add criteria').click()
... browser.getControl('Comment').selected = True
... browser.getControl('Save', index=0).click()
>>> print browser.contents
<...Changes saved...
View the collection listing.
>>> browser.getLink('View').click()
>>> browser.getLink('admin on Doc1', index=0)
<Link text='admin on Doc1' url='http://nohost/plone/doc1/++conversation++default/...'>
>>> browser.getLink('admin on Doc1', index=1)
<Link text='admin on Doc1' url='http://nohost/plone/doc1/++conversation++default/...'>
>>> browser.getLink('Anonymous on Doc1', index=0)
<Link text='Anonymous on Doc1' url='http://nohost/plone/doc1/++conversation++default/...'>
>>> browser.getLink('Anonymous on Doc1', index=1)
<Link text='Anonymous on Doc1' url='http://nohost/plone/doc1/++conversation++default/...'>
>>> open('/tmp/testbrowser.html', 'w').write(browser.contents)
>>> browser.getLink(tarek_fullname + ' on Doc1')
<Link text='Tarek Ziad\xc3\xa9 on Doc1' url='http://nohost/plone/doc1/++conversation++default/...'>
>>> browser.getLink(jim_fullname + ' on Doc1')
<Link text='Jim Fult\xc3\xb8rn on Doc1' url='http://nohost/plone/doc1/++conversation++default/...'>
Comments are unindexed when the content is deleted
--------------------------------------------------
Delete the commented content.
>>> browser.open(urldoc1)
>>> browser.getLink('Delete').click()
>>> browser.getControl('Delete').click()
>>> print browser.contents
<...Doc1 has been deleted...
The comments are no longer in the catalog.
>>> browser.open(topic_url)
>>> browser.getLink('admin on Doc1', index=0)
Traceback (most recent call last):
LinkNotFoundError
>>> browser.getLink('admin on Doc1', index=1)
Traceback (most recent call last):
LinkNotFoundError
>>> browser.getLink('Anonymous on Doc1', index=0)
Traceback (most recent call last):
LinkNotFoundError
>>> browser.getLink('Anonymous on Doc1', index=1)
Traceback (most recent call last):
LinkNotFoundError
>>> browser.getLink(tarek_fullname + ' on Doc1')
Traceback (most recent call last):
LinkNotFoundError
>>> browser.getLink(jim_fullname + ' on Doc1')
Traceback (most recent call last):
LinkNotFoundError

View File

@ -1,41 +0,0 @@
plone.app.discussion javascript testsuite
=========================================
Note: This document was shamelessly stolen from the plone.app.deco package.
We're using QUnit_ for unit testing, the jQuery test runner.
Simply load index.html directly in the browser with a file:/// url; not via
Plone. This way our tests are truely standalone and isolated.
Coverage testing
----------------
To test code coverage, I can heartily recommend using JSCoverage_. You can
download, compile and install it by:
$ wget http://siliconforks.com/jscoverage/download/jscoverage-0.5.tar.bz2
$ tar xfvj jscoverage-0.5.tar.bz2
$ cd jscoverage-0.5
$ ./configure
$ make
$ sudo make install
After that, issue the following command to run it from your Plone buildout:
$ jscoverage-server -v --ip-address=0.0.0.0 --port=8080 --encoding=UTF-8 \
--document-root=plone/app/discussion/ --no-instrument=/tests
Then point your browser to the now running `coverage server
<http://localhost:8080/jscoverage.html?/tests/javascripts/test_comments.html>`__, and
the test suite will run instrumented in an iframe. Select the Summary tab to see
the results.
The command-line options ensure that only our tests and the modules being
tested are instrumented for coverage, not the testing framework nor jQuery.
Note that JSCoverage adds instrumentation statements to the code, so don't try
to debug your tests when running via the jscoverage server.
.. _QUnit: http://docs.jquery.com/QUnit
.. _JSCoverage: http://siliconforks.com/jscoverage/

View File

@ -1,154 +0,0 @@
/*!
* jQuery JavaScript Library v1.4.2
* http://jquery.com/
*
* Copyright 2010, John Resig
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* Includes Sizzle.js
* http://sizzlejs.com/
* Copyright 2010, The Dojo Foundation
* Released under the MIT, BSD, and GPL Licenses.
*
* Date: Sat Feb 13 22:33:48 2010 -0500
*/
(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),
function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);

View File

@ -1,42 +0,0 @@
<!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" xml:lang="en" lang="en"
dir="ltr" id="html">
<head>
<title>plone.app.discussion comments Test Suite</title>
<!-- qUnit -->
<link rel="stylesheet" href="../qunit/qunit.css" type="text/css"
media="screen" />
<script type="text/javascript" src="../qunit/qunit.js"></script>
<!-- jQuery -->
<script type="text/javascript" src="jquery.js"></script>
<!-- plone.app.discussion -->
<script type="text/javascript" src="../../browser/javascripts/comments.js">
</script>
<!-- Tests -->
<script type="text/javascript" src="test_comments.js"></script>
</head>
<body>
<h1 id="qunit-header">plone.app.discussion comments Test
Suite</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar">
</div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests">
</ol>
</body>
</html>

View File

@ -1,146 +0,0 @@
$(document).ready(function () {
/* TEST SETUP */
module("comments", {
setup: function () {
// Create a comments section with one comment inside
//
// <div class="discussion">
// <div id="1282720906349675" class="comment">
// <div class="commentBody">
// <p>Lorem ipsum.</p>
// </div>
// <div class="commentActions">
// <button class="reply-to-comment-button"></button>
// </div>
// </div>
// </div>
var comments = $(document.createElement("div"))
.addClass("discussion")
.append($(document.createElement("div"))
.addClass("comment")
.attr("id", "1282720906349675")
.append($(document.createElement("div"))
.addClass("commentBody")
.append($(document.createElement("p"))
.text("Lorem ipsum.")
)
)
.append($(document.createElement("div"))
.addClass("commentActions")
.append($(document.createElement("button"))
.addClass("reply-to-comment-button")
))
);
$(document.body).append(comments);
// Create a basic commenting form
//
// <form class="form">
// <div class="formfield-form-widgets-in_reply_to">
// <input name="form.widgets.in_reply_to">
// </div>
// <div class="formfield-form-widgets-author_name">
// <input name="form.widgets.author" type="text">
// </div>
// <div class="formfield-form-widgets-text">
// <textarea name="form.widgets.text"></textarea>
// </div>
// <div class="formControls">
// <input name="form.buttons.comment">
// <input name="form.buttons.cancel">
// </div>
// </form>
var commentform = $(document.createElement("div"))
.append($(document.createElement("form"))
.addClass("form")
.append($(document.createElement("div"))
.addClass("formfield-form-widgets-in_reply_to")
.append($(document.createElement("input"))
.attr("name", "form.widgets.in_reply_to")
.val("")
)
)
.append($(document.createElement("div"))
.addClass("formfield-form-widgets-author_name")
.append($(document.createElement("input"))
.attr("name", "form.widgets.author")
.attr("type", "text")
)
)
.append($(document.createElement("div"))
.addClass("formfield-form-widgets-text")
.append($(document.createElement("textarea"))
.attr("name", "form.widgets.text")
)
)
.append($(document.createElement("div"))
.addClass("formControls")
.append($(document.createElement("input"))
.attr("name", "form.buttons.comment"))
.append($(document.createElement("input"))
.attr("name", "form.buttons.cancel"))
)
)
.addClass("reply")
.attr("id", "commenting");
$(document.body).append(commentform);
},
teardown: function () {
$("#commenting").remove();
$(".discussion").remove();
}
});
/* TESTS */
test("Hide the reply and the cancel button for the comment form", function(){
expect(1);
$(".reply").find("input[name='form.buttons.cancel']").css("display", "none");
equals($("input[name='form.buttons.cancel']").css("display"), "none", "The cancel button should be hidden");
});
test("Show the reply button only when Javascript is enabled", function(){
expect(1);
$(".reply-to-comment-button").css("display", "inline");
equals($("button[class='reply-to-comment-button']").attr("style"), "display: inline;", "The reply button should show up when Javascript is enabled");
});
test("Create a comment reply form.", function() {
expect(2);
var comment_div = $("#1282720906349675");
var reply_button = comment_div.children(".reply-to-comment-button");
$.createReplyForm(comment_div);
var reply_form = comment_div.children(".reply");
ok(reply_form.find("input[name='form.widgets.in_reply_to']"), "Reply form has been copied");
same(reply_form.find("input[name='form.widgets.in_reply_to']").val(), "1282720906349675", "The reply for should have the id of the comment in the in_reply_to field");
});
test("Clear all form values from a form.", function() {
// Create a reply form with some values
var comment_div = $("#1282720906349675");
$.createReplyForm(comment_div);
var reply_form = comment_div.find(".reply");
var author = reply_form.find("input[name='form.widgets.author']");
var text = comment_div.find("input[name='form.widgets.text']");
author.val("my author");
text.val("my text");
// Call the clearForm function to clear the form
$.clearForm(comment_div);
// Check if all form fields have been cleared
var author = comment_div.find("input[name='form.widgets.author']");
var text = comment_div.find("input[name='form.widgets.text']");
equals(author.val(), "", "The author form value should be empty");
equals(text.text(), "", "The text form value should be empty");
});
});

View File

@ -1,40 +0,0 @@
<!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" xml:lang="en" lang="en"
dir="ltr" id="html">
<head>
<title>plone.app.discussion moderation Test Suite</title>
<!-- qUnit -->
<link rel="stylesheet" href="../qunit/qunit.css" type="text/css"
media="screen" />
<script type="text/javascript" src="../qunit/qunit.js"></script>
<!-- jQuery -->
<script type="text/javascript" src="jquery.js"></script>
<!-- plone.app.discussion -->
<script type="text/javascript" src="../../browser/javascripts/moderation.js">
</script>
<!-- Tests -->
<script type="text/javascript" src="test_moderation.js"></script>
</head>
<body>
<h1 id="qunit-header">plone.app.discussion moderation Test Suite</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
</body>
</html>

View File

@ -1,72 +0,0 @@
/* TEST SETUP */
module("comments", {
setup: function () {
// <form>
// <table id="review-comments">
// <tbody>
// <tr>
// <td>
// <a href="http://localhost:8080/Plone/front-page/++conversation++default/1285339036601284">My comment</a>
// </td>
// <td class="actions">
// <input id="1285339036601284" class="context comment-publish-button" type="submit" value="Publish" name="form.button.Publish" />
// <input id="1285339036601284" class="destructive comment-delete-button" type="submit" value="Delete" name="form.button.Delete" />
// </td>
// </tr>
// </tbody>
// </table>
// </form>
var review_table = $(document.createElement("form"))
.append($(document.createElement("table"))
.attr("id", "review-comments")
.append($(document.createElement("tbody"))
.append($(document.createElement("tr"))
.append($(document.createElement("td"))
.append($(document.createElement("a"))
.text("My comment.")
.attr("href", "http://localhost:8080/Plone/front-page/++conversation++default/1285339036601284")
)
)
.append($(document.createElement("td"))
.append($(document.createElement("input"))
.attr("id", "1285339036601284")
.attr("value", "Publish")
.attr("name", "form.button.Publish")
)
.append($(document.createElement("input"))
.attr("id", "1285339036601284")
.attr("value", "Delete")
.attr("name", "form.button.Delete")
)
.addClass("actions")
)
)
)
);
$(document.body).append(review_table);
},
teardown: function () {
$("form").remove();
}
});
/* TESTS */
test("Delete a single comment", function(){
expect(1);
stop();
var delete_button = $(".actions").children("input[name='form.button.Delete']");
delete_button.trigger('click');
start();
equals($("#1285339036601284").attr("name", "form.button.Delete").length, 0, "The comment row should have been deleted.");
});
test("Publish a single comment", function(){
expect(1);
var publish_button = $(".actions").children("input[name='form.button.Publish']");
publish_button.trigger('click');
equals($("#1285339036601284").attr("name", "form.button.Publish").length, 0, "The comment row should have been removed since the comment has been published.");
});

View File

@ -1,18 +0,0 @@
server: http://localhost:9876
load:
# Add these lines to load the equiv function and adapter in order, before the
# tests (assuming they are saved to tests/qunit/)
- qunit/equiv.js
- qunit/QUnitAdapter.js
# This is where we load the qunit tests
- javascripts/*.js
# And this loads the source files we are testing
- ../browser/javascripts/*.js
plugin:
- name: "coverage"
jar: "../../../../parts/jstestdriver/coverage.jar"
module: "com.google.jstestdriver.coverage.CoverageModule"

View File

@ -1,5 +0,0 @@
==============
JS TEST DRIVER
==============
java -jar JsTestDriver.jar --port 9876 --config jsTestDriver.conf --browser /usr/bin/firefox --tests all

View File

@ -1,85 +0,0 @@
/*
QUnitAdapter
Version: 1.1.0
Run qunit tests using JS Test Driver
This provides almost the same api as qunit.
Tests must run sychronously, which means no use of stop and start methods.
You can use jsUnit Clock object to deal with timeouts and intervals:
http://googletesting.blogspot.com/2007/03/javascript-simulating-time-in-jsunit.html
The qunit #main DOM element is not included. If you need to do any DOM manipulation
you need to set it up and tear it down in each test.
*/
(function() {
if(!(window.equiv)) {
throw new Error("QUnitAdapter.js - Unable to find equiv function. Ensure you have added equiv.js to the load section of your jsTestDriver.conf");
}
var QUnitTestCase;
window.module = function(name, lifecycle) {
QUnitTestCase = TestCase(name);
QUnitTestCase.prototype.lifecycle = lifecycle || {};
};
window.test = function(name, expected, test) {
QUnitTestCase.prototype['test ' + name] = function() {
if(this.lifecycle.setup) {
this.lifecycle.setup();
}
if(expected.constructor === Number) {
expectAsserts(expected);
} else {
test = expected;
}
test.call(this.lifecycle);
if(this.lifecycle.teardown) {
this.lifecycle.teardown();
}
};
};
window.expect = function(count) {
expectAsserts(count);
};
window.ok = function(actual, msg) {
assertTrue(msg ? msg : '', !!actual);
};
window.equals = function(a, b, msg) {
assertEqual(msg ? msg : '', b, a);
};
window.start = window.stop = function() {
fail('start and stop methods are not available when using JS Test Driver.\n' +
'Use jsUnit Clock object to deal with timeouts and intervals:\n' +
'http://googletesting.blogspot.com/2007/03/javascript-simulating-time-in-jsunit.html.');
};
window.same = function(a, b, msg) {
assertTrue(msg ? msg : '', window.equiv(b, a));
};
window.reset = function() {
fail('reset method is not available when using JS Test Driver');
};
window.isLocal = function() {
return false;
};
window.QUnit = {
equiv: window.equiv,
ok: window.ok
};
module('Default Module');
})();

View File

@ -1,185 +0,0 @@
// Tests for equality any JavaScript type and structure without unexpected results.
// Discussions and reference: http://philrathe.com/articles/equiv
// Test suites: http://philrathe.com/tests/equiv
// Author: Philippe Rath <prathe@gmail.com>
window.equiv = function () {
var innerEquiv; // the real equiv function
var callers = []; // stack to decide between skip/abort functions
// Determine what is o.
function hoozit(o) {
if (typeof o === "string") {
return "string";
} else if (typeof o === "boolean") {
return "boolean";
} else if (typeof o === "number") {
if (isNaN(o)) {
return "nan";
} else {
return "number";
}
} else if (typeof o === "undefined") {
return "undefined";
// consider: typeof null === object
} else if (o === null) {
return "null";
// consider: typeof [] === object
} else if (o instanceof Array) {
return "array";
// consider: typeof new Date() === object
} else if (o instanceof Date) {
return "date";
// consider: /./ instanceof Object;
// /./ instanceof RegExp;
// typeof /./ === "function"; // => false in IE and Opera,
// true in FF and Safari
} else if (o instanceof RegExp) {
return "regexp";
} else if (typeof o === "object") {
return "object";
} else if (o instanceof Function) {
return "function";
}
}
// Call the o related callback with the given arguments.
function bindCallbacks(o, callbacks, args) {
var prop = hoozit(o);
if (prop) {
if (hoozit(callbacks[prop]) === "function") {
return callbacks[prop].apply(callbacks, args);
} else {
return callbacks[prop]; // or undefined
}
}
}
var callbacks = function () {
// for string, boolean, number and null
function useStrictEquality(b, a) {
return a === b;
}
return {
"string": useStrictEquality,
"boolean": useStrictEquality,
"number": useStrictEquality,
"null": useStrictEquality,
"undefined": useStrictEquality,
"nan": function (b) {
return isNaN(b);
},
"date": function (b, a) {
return hoozit(b) === "date" && a.valueOf() === b.valueOf();
},
"regexp": function (b, a) {
return hoozit(b) === "regexp" &&
a.source === b.source && // the regex itself
a.global === b.global && // and its modifers (gmi) ...
a.ignoreCase === b.ignoreCase &&
a.multiline === b.multiline;
},
// - skip when the property is a method of an instance (OOP)
// - abort otherwise,
// initial === would have catch identical references anyway
"function": function () {
var caller = callers[callers.length - 1];
return caller !== Object &&
typeof caller !== "undefined";
},
"array": function (b, a) {
var i;
var len;
// b could be an object literal here
if ( ! (hoozit(b) === "array")) {
return false;
}
len = a.length;
if (len !== b.length) { // safe and faster
return false;
}
for (i = 0; i < len; i++) {
if( ! innerEquiv(a[i], b[i])) {
return false;
}
}
return true;
},
"object": function (b, a) {
var i;
var eq = true; // unless we can proove it
var aProperties = [], bProperties = []; // collection of strings
// comparing constructors is more strict than using instanceof
if ( a.constructor !== b.constructor) {
return false;
}
// stack constructor before traversing properties
callers.push(a.constructor);
for (i in a) { // be strict: don't ensures hasOwnProperty and go deep
aProperties.push(i); // collect a's properties
if ( ! innerEquiv(a[i], b[i])) {
eq = false;
}
}
callers.pop(); // unstack, we are done
for (i in b) {
bProperties.push(i); // collect b's properties
}
// Ensures identical properties name
return eq && innerEquiv(aProperties.sort(), bProperties.sort());
}
};
}();
innerEquiv = function () { // can take multiple arguments
var args = Array.prototype.slice.apply(arguments);
if (args.length < 2) {
return true; // end transition
}
return (function (a, b) {
if (a === b) {
return true; // catch the most you can
} else if (typeof a !== typeof b || a === null || b === null || typeof a === "undefined" || typeof b === "undefined") {
return false; // don't lose time with error prone cases
} else {
return bindCallbacks(a, callbacks, [b, a]);
}
// apply transition with (1..n) arguments
})(args[0], args[1]) && arguments.callee.apply(this, args.splice(1, args.length -1));
};
return innerEquiv;
}(); // equiv

View File

@ -1,17 +0,0 @@
h1#qunit-header { padding: 15px; font-size: large; background-color: #06b; color: white; font-family: 'trebuchet ms', verdana, arial; margin: 0; }
h1#qunit-header a { color: white; }
h2#qunit-banner { height: 2em; border-bottom: 1px solid white; background-color: #eee; margin: 0; font-family: 'trebuchet ms', verdana, arial; }
h2#qunit-banner.pass { background-color: green; }
h2#qunit-banner.fail { background-color: red; }
h2#qunit-userAgent { padding: 10px; background-color: #eee; color: black; margin: 0; font-size: small; font-weight: normal; font-family: 'trebuchet ms', verdana, arial; font-size: 10pt; }
div#qunit-testrunner-toolbar { background: #eee; border-top: 1px solid black; padding: 10px; font-family: 'trebuchet ms', verdana, arial; margin: 0; font-size: 10pt; }
ol#qunit-tests { font-family: 'trebuchet ms', verdana, arial; font-size: 10pt; }
ol#qunit-tests li strong { cursor:pointer; }
ol#qunit-tests .pass { color: green; }
ol#qunit-tests .fail { color: red; }
p#qunit-testresult { margin-left: 1em; font-size: 10pt; font-family: 'trebuchet ms', verdana, arial; }

View File

@ -1,997 +0,0 @@
/*
* QUnit - A JavaScript Unit Testing Framework
*
* http://docs.jquery.com/QUnit
*
* Copyright (c) 2009 John Resig, Jörn Zaefferer
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*/
(function(window) {
var QUnit = {
// Initialize the configuration options
init: function init() {
config = {
stats: { all: 0, bad: 0 },
moduleStats: { all: 0, bad: 0 },
started: +new Date,
blocking: false,
autorun: false,
assertions: [],
filters: [],
queue: []
};
var tests = id("qunit-tests"),
banner = id("qunit-banner"),
result = id("qunit-testresult");
if ( tests ) {
tests.innerHTML = "";
}
if ( banner ) {
banner.className = "";
}
if ( result ) {
result.parentNode.removeChild( result );
}
},
// call on start of module test to prepend name to all tests
module: function module(name, testEnvironment) {
synchronize(function() {
if ( config.currentModule ) {
QUnit.moduleDone( config.currentModule, config.moduleStats.bad, config.moduleStats.all );
}
config.currentModule = name;
config.moduleTestEnvironment = testEnvironment;
config.moduleStats = { all: 0, bad: 0 };
QUnit.moduleStart( name, testEnvironment );
});
},
asyncTest: function asyncTest(testName, expected, callback) {
if ( arguments.length === 2 ) {
callback = expected;
expected = 0;
}
QUnit.test(testName, expected, callback, true);
},
test: function test(testName, expected, callback, async) {
var name = testName, testEnvironment = {};
if ( arguments.length === 2 ) {
callback = expected;
expected = null;
}
if ( config.currentModule ) {
name = config.currentModule + " module: " + name;
}
if ( !validTest(name) ) {
return;
}
synchronize(function() {
QUnit.testStart( testName );
testEnvironment = extend({
setup: function() {},
teardown: function() {}
}, config.moduleTestEnvironment);
config.assertions = [];
config.expected = null;
if ( arguments.length >= 3 ) {
config.expected = callback;
callback = arguments[2];
}
try {
if ( !config.pollution ) {
saveGlobal();
}
testEnvironment.setup.call(testEnvironment);
} catch(e) {
QUnit.ok( false, "Setup failed on " + name + ": " + e.message );
}
if ( async ) {
QUnit.stop();
}
try {
callback.call(testEnvironment);
} catch(e) {
fail("Test " + name + " died, exception and test follows", e, callback);
QUnit.ok( false, "Died on test #" + (config.assertions.length + 1) + ": " + e.message );
// else next test will carry the responsibility
saveGlobal();
// Restart the tests if they're blocking
if ( config.blocking ) {
start();
}
}
});
synchronize(function() {
try {
checkPollution();
testEnvironment.teardown.call(testEnvironment);
} catch(e) {
QUnit.ok( false, "Teardown failed on " + name + ": " + e.message );
}
try {
QUnit.reset();
} catch(e) {
fail("reset() failed, following Test " + name + ", exception and reset fn follows", e, reset);
}
if ( config.expected && config.expected != config.assertions.length ) {
QUnit.ok( false, "Expected " + config.expected + " assertions, but " + config.assertions.length + " were run" );
}
var good = 0, bad = 0,
tests = id("qunit-tests");
config.stats.all += config.assertions.length;
config.moduleStats.all += config.assertions.length;
if ( tests ) {
var ol = document.createElement("ol");
ol.style.display = "none";
for ( var i = 0; i < config.assertions.length; i++ ) {
var assertion = config.assertions[i];
var li = document.createElement("li");
li.className = assertion.result ? "pass" : "fail";
li.innerHTML = assertion.message || "(no message)";
ol.appendChild( li );
if ( assertion.result ) {
good++;
} else {
bad++;
config.stats.bad++;
config.moduleStats.bad++;
}
}
var b = document.createElement("strong");
b.innerHTML = name + " <b style='color:black;'>(<b class='fail'>" + bad + "</b>, <b class='pass'>" + good + "</b>, " + config.assertions.length + ")</b>";
addEvent(b, "click", function() {
var next = b.nextSibling, display = next.style.display;
next.style.display = display === "none" ? "block" : "none";
});
addEvent(b, "dblclick", function(e) {
var target = (e || window.event).target;
if ( target.nodeName.toLowerCase() === "strong" ) {
var text = "", node = target.firstChild;
while ( node.nodeType === 3 ) {
text += node.nodeValue;
node = node.nextSibling;
}
text = text.replace(/(^\s*|\s*$)/g, "");
if ( window.location ) {
window.location.href = window.location.href.match(/^(.+?)(\?.*)?$/)[1] + "?" + encodeURIComponent(text);
}
}
});
var li = document.createElement("li");
li.className = bad ? "fail" : "pass";
li.appendChild( b );
li.appendChild( ol );
tests.appendChild( li );
if ( bad ) {
var toolbar = id("qunit-testrunner-toolbar");
if ( toolbar ) {
toolbar.style.display = "block";
id("qunit-filter-pass").disabled = null;
id("qunit-filter-missing").disabled = null;
}
}
} else {
for ( var i = 0; i < config.assertions.length; i++ ) {
if ( !config.assertions[i].result ) {
bad++;
config.stats.bad++;
config.moduleStats.bad++;
}
}
}
QUnit.testDone( testName, bad, config.assertions.length );
if ( !window.setTimeout && !config.queue.length ) {
done();
}
});
if ( window.setTimeout && !config.doneTimer ) {
config.doneTimer = window.setTimeout(function(){
if ( !config.queue.length ) {
done();
} else {
synchronize( done );
}
}, 13);
}
},
/**
* Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.
*/
expect: function expect(asserts) {
config.expected = asserts;
},
/**
* Asserts true.
* @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
*/
ok: function ok(a, msg) {
QUnit.log(a, msg);
config.assertions.push({
result: !!a,
message: msg
});
},
/**
* Checks that the first two arguments are equal, with an optional message.
* Prints out both actual and expected values.
*
* Prefered to ok( actual == expected, message )
*
* @example equals( format("Received {0} bytes.", 2), "Received 2 bytes." );
*
* @param Object actual
* @param Object expected
* @param String message (optional)
*/
equals: function equals(actual, expected, message) {
push(expected == actual, actual, expected, message);
},
same: function(a, b, message) {
push(QUnit.equiv(a, b), a, b, message);
},
start: function start() {
// A slight delay, to avoid any current callbacks
if ( window.setTimeout ) {
window.setTimeout(function() {
if ( config.timeout ) {
clearTimeout(config.timeout);
}
config.blocking = false;
process();
}, 13);
} else {
config.blocking = false;
process();
}
},
stop: function stop(timeout) {
config.blocking = true;
if ( timeout && window.setTimeout ) {
config.timeout = window.setTimeout(function() {
QUnit.ok( false, "Test timed out" );
QUnit.start();
}, timeout);
}
},
/**
* Resets the test setup. Useful for tests that modify the DOM.
*/
reset: function reset() {
if ( window.jQuery ) {
jQuery("#main").html( config.fixture );
jQuery.event.global = {};
jQuery.ajaxSettings = extend({}, config.ajaxSettings);
}
},
/**
* Trigger an event on an element.
*
* @example triggerEvent( document.body, "click" );
*
* @param DOMElement elem
* @param String type
*/
triggerEvent: function triggerEvent( elem, type, event ) {
if ( document.createEvent ) {
event = document.createEvent("MouseEvents");
event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView,
0, 0, 0, 0, 0, false, false, false, false, 0, null);
elem.dispatchEvent( event );
} else if ( elem.fireEvent ) {
elem.fireEvent("on"+type);
}
},
// Logging callbacks
done: function done(failures, total) {},
log: function log(result, message) {},
testStart: function testStart(name) {},
testDone: function testDone(name, failures, total) {},
moduleStart: function moduleStart(name, testEnvironment) {},
moduleDone: function moduleDone(name, failures, total) {}
};
// Maintain internal state
var config = {
// The queue of tests to run
queue: [],
// block until document ready
blocking: true
};
// Load paramaters
(function() {
var location = window.location || { search: "", protocol: "file:" },
GETParams = location.search.slice(1).split('&');
for ( var i = 0; i < GETParams.length; i++ ) {
GETParams[i] = decodeURIComponent( GETParams[i] );
if ( GETParams[i] === "noglobals" ) {
GETParams.splice( i, 1 );
i--;
config.noglobals = true;
}
}
// restrict modules/tests by get parameters
config.filters = GETParams;
// Figure out if we're running the tests from a server or not
QUnit.isLocal = !!(location.protocol === 'file:');
})();
// Expose the API as global variables, unless an 'exports'
// object exists, in that case we assume we're in CommonJS
if ( typeof exports === "undefined" || typeof require === "undefined" ) {
extend(window, QUnit);
window.QUnit = QUnit;
} else {
extend(exports, QUnit);
exports.QUnit = QUnit;
}
if ( typeof document === "undefined" || document.readyState === "complete" ) {
config.autorun = true;
}
addEvent(window, "load", function() {
// Initialize the config, saving the execution queue
var oldconfig = extend({}, config);
QUnit.init();
extend(config, oldconfig);
config.blocking = false;
var userAgent = id("qunit-userAgent");
if ( userAgent ) {
userAgent.innerHTML = navigator.userAgent;
}
var toolbar = id("qunit-testrunner-toolbar");
if ( toolbar ) {
toolbar.style.display = "none";
var filter = document.createElement("input");
filter.type = "checkbox";
filter.id = "qunit-filter-pass";
filter.disabled = true;
addEvent( filter, "click", function() {
var li = document.getElementsByTagName("li");
for ( var i = 0; i < li.length; i++ ) {
if ( li[i].className.indexOf("pass") > -1 ) {
li[i].style.display = filter.checked ? "none" : "block";
}
}
});
toolbar.appendChild( filter );
var label = document.createElement("label");
label.setAttribute("for", "filter-pass");
label.innerHTML = "Hide passed tests";
toolbar.appendChild( label );
var missing = document.createElement("input");
missing.type = "checkbox";
missing.id = "qunit-filter-missing";
missing.disabled = true;
addEvent( missing, "click", function() {
var li = document.getElementsByTagName("li");
for ( var i = 0; i < li.length; i++ ) {
if ( li[i].className.indexOf("fail") > -1 && li[i].innerHTML.indexOf('missing test - untested code is broken code') > - 1 ) {
li[i].parentNode.parentNode.style.display = missing.checked ? "none" : "block";
}
}
});
toolbar.appendChild( missing );
label = document.createElement("label");
label.setAttribute("for", "filter-missing");
label.innerHTML = "Hide missing tests (untested code is broken code)";
toolbar.appendChild( label );
}
var main = id('main');
if ( main ) {
config.fixture = main.innerHTML;
}
if ( window.jQuery ) {
config.ajaxSettings = window.jQuery.ajaxSettings;
}
QUnit.start();
});
function done() {
if ( config.doneTimer && window.clearTimeout ) {
window.clearTimeout( config.doneTimer );
config.doneTimer = null;
}
if ( config.queue.length ) {
config.doneTimer = window.setTimeout(function(){
if ( !config.queue.length ) {
done();
} else {
synchronize( done );
}
}, 13);
return;
}
config.autorun = true;
// Log the last module results
if ( config.currentModule ) {
QUnit.moduleDone( config.currentModule, config.moduleStats.bad, config.moduleStats.all );
}
var banner = id("qunit-banner"),
tests = id("qunit-tests"),
html = ['Tests completed in ',
+new Date - config.started, ' milliseconds.<br/>',
'<span class="bad">', config.stats.all - config.stats.bad, '</span> tests of <span class="all">', config.stats.all, '</span> passed, ', config.stats.bad,' failed.'].join('');
if ( banner ) {
banner.className += " " + (config.stats.bad ? "fail" : "pass");
}
if ( tests ) {
var result = id("qunit-testresult");
if ( !result ) {
result = document.createElement("p");
result.id = "qunit-testresult";
result.className = "result";
tests.parentNode.insertBefore( result, tests.nextSibling );
}
result.innerHTML = html;
}
QUnit.done( config.stats.bad, config.stats.all );
}
function validTest( name ) {
var i = config.filters.length,
run = false;
if ( !i ) {
return true;
}
while ( i-- ) {
var filter = config.filters[i],
not = filter.charAt(0) == '!';
if ( not ) {
filter = filter.slice(1);
}
if ( name.indexOf(filter) !== -1 ) {
return !not;
}
if ( not ) {
run = true;
}
}
return run;
}
function push(result, actual, expected, message) {
message = message || (result ? "okay" : "failed");
QUnit.ok( result, result ? message + ": " + expected : message + ", expected: " + QUnit.jsDump.parse(expected) + " result: " + QUnit.jsDump.parse(actual) );
}
function synchronize( callback ) {
config.queue.push( callback );
if ( config.autorun && !config.blocking ) {
process();
}
}
function process() {
while ( config.queue.length && !config.blocking ) {
config.queue.shift()();
}
}
function saveGlobal() {
config.pollution = [];
if ( config.noglobals ) {
for ( var key in window ) {
config.pollution.push( key );
}
}
}
function checkPollution( name ) {
var old = config.pollution;
saveGlobal();
var newGlobals = diff( old, config.pollution );
if ( newGlobals.length > 0 ) {
ok( false, "Introduced global variable(s): " + newGlobals.join(", ") );
config.expected++;
}
var deletedGlobals = diff( config.pollution, old );
if ( deletedGlobals.length > 0 ) {
ok( false, "Deleted global variable(s): " + deletedGlobals.join(", ") );
config.expected++;
}
}
// returns a new Array with the elements that are in a but not in b
function diff( a, b ) {
var result = a.slice();
for ( var i = 0; i < result.length; i++ ) {
for ( var j = 0; j < b.length; j++ ) {
if ( result[i] === b[j] ) {
result.splice(i, 1);
i--;
break;
}
}
}
return result;
}
function fail(message, exception, callback) {
if ( typeof console !== "undefined" && console.error && console.warn ) {
console.error(message);
console.error(exception);
console.warn(callback.toString());
} else if ( window.opera && opera.postError ) {
opera.postError(message, exception, callback.toString);
}
}
function extend(a, b) {
for ( var prop in b ) {
a[prop] = b[prop];
}
return a;
}
function addEvent(elem, type, fn) {
if ( elem.addEventListener ) {
elem.addEventListener( type, fn, false );
} else if ( elem.attachEvent ) {
elem.attachEvent( "on" + type, fn );
} else {
fn();
}
}
function id(name) {
return !!(typeof document !== "undefined" && document && document.getElementById) &&
document.getElementById( name );
}
// Test for equality any JavaScript type.
// Discussions and reference: http://philrathe.com/articles/equiv
// Test suites: http://philrathe.com/tests/equiv
// Author: Philippe Rathé <prathe@gmail.com>
QUnit.equiv = function () {
var innerEquiv; // the real equiv function
var callers = []; // stack to decide between skip/abort functions
// Determine what is o.
function hoozit(o) {
if (o.constructor === String) {
return "string";
} else if (o.constructor === Boolean) {
return "boolean";
} else if (o.constructor === Number) {
if (isNaN(o)) {
return "nan";
} else {
return "number";
}
} else if (typeof o === "undefined") {
return "undefined";
// consider: typeof null === object
} else if (o === null) {
return "null";
// consider: typeof [] === object
} else if (o instanceof Array) {
return "array";
// consider: typeof new Date() === object
} else if (o instanceof Date) {
return "date";
// consider: /./ instanceof Object;
// /./ instanceof RegExp;
// typeof /./ === "function"; // => false in IE and Opera,
// true in FF and Safari
} else if (o instanceof RegExp) {
return "regexp";
} else if (typeof o === "object") {
return "object";
} else if (o instanceof Function) {
return "function";
} else {
return undefined;
}
}
// Call the o related callback with the given arguments.
function bindCallbacks(o, callbacks, args) {
var prop = hoozit(o);
if (prop) {
if (hoozit(callbacks[prop]) === "function") {
return callbacks[prop].apply(callbacks, args);
} else {
return callbacks[prop]; // or undefined
}
}
}
var callbacks = function () {
// for string, boolean, number and null
function useStrictEquality(b, a) {
if (b instanceof a.constructor || a instanceof b.constructor) {
// to catch short annotaion VS 'new' annotation of a declaration
// e.g. var i = 1;
// var j = new Number(1);
return a == b;
} else {
return a === b;
}
}
return {
"string": useStrictEquality,
"boolean": useStrictEquality,
"number": useStrictEquality,
"null": useStrictEquality,
"undefined": useStrictEquality,
"nan": function (b) {
return isNaN(b);
},
"date": function (b, a) {
return hoozit(b) === "date" && a.valueOf() === b.valueOf();
},
"regexp": function (b, a) {
return hoozit(b) === "regexp" &&
a.source === b.source && // the regex itself
a.global === b.global && // and its modifers (gmi) ...
a.ignoreCase === b.ignoreCase &&
a.multiline === b.multiline;
},
// - skip when the property is a method of an instance (OOP)
// - abort otherwise,
// initial === would have catch identical references anyway
"function": function () {
var caller = callers[callers.length - 1];
return caller !== Object &&
typeof caller !== "undefined";
},
"array": function (b, a) {
var i;
var len;
// b could be an object literal here
if ( ! (hoozit(b) === "array")) {
return false;
}
len = a.length;
if (len !== b.length) { // safe and faster
return false;
}
for (i = 0; i < len; i++) {
if ( ! innerEquiv(a[i], b[i])) {
return false;
}
}
return true;
},
"object": function (b, a) {
var i;
var eq = true; // unless we can proove it
var aProperties = [], bProperties = []; // collection of strings
// comparing constructors is more strict than using instanceof
if ( a.constructor !== b.constructor) {
return false;
}
// stack constructor before traversing properties
callers.push(a.constructor);
for (i in a) { // be strict: don't ensures hasOwnProperty and go deep
aProperties.push(i); // collect a's properties
if ( ! innerEquiv(a[i], b[i])) {
eq = false;
}
}
callers.pop(); // unstack, we are done
for (i in b) {
bProperties.push(i); // collect b's properties
}
// Ensures identical properties name
return eq && innerEquiv(aProperties.sort(), bProperties.sort());
}
};
}();
innerEquiv = function () { // can take multiple arguments
var args = Array.prototype.slice.apply(arguments);
if (args.length < 2) {
return true; // end transition
}
return (function (a, b) {
if (a === b) {
return true; // catch the most you can
} else if (a === null || b === null || typeof a === "undefined" || typeof b === "undefined" || hoozit(a) !== hoozit(b)) {
return false; // don't lose time with error prone cases
} else {
return bindCallbacks(a, callbacks, [b, a]);
}
// apply transition with (1..n) arguments
})(args[0], args[1]) && arguments.callee.apply(this, args.splice(1, args.length -1));
};
return innerEquiv;
}();
/**
* jsDump
* Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
* Licensed under BSD (http://www.opensource.org/licenses/bsd-license.php)
* Date: 5/15/2008
* @projectDescription Advanced and extensible data dumping for Javascript.
* @version 1.0.0
* @author Ariel Flesler
* @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html}
*/
QUnit.jsDump = (function() {
function quote( str ) {
return '"' + str.toString().replace(/"/g, '\\"') + '"';
};
function literal( o ) {
return o + '';
};
function join( pre, arr, post ) {
var s = jsDump.separator(),
base = jsDump.indent(),
inner = jsDump.indent(1);
if ( arr.join )
arr = arr.join( ',' + s + inner );
if ( !arr )
return pre + post;
return [ pre, inner + arr, base + post ].join(s);
};
function array( arr ) {
var i = arr.length, ret = Array(i);
this.up();
while ( i-- )
ret[i] = this.parse( arr[i] );
this.down();
return join( '[', ret, ']' );
};
var reName = /^function (\w+)/;
var jsDump = {
parse:function( obj, type ) { //type is used mostly internally, you can fix a (custom)type in advance
var parser = this.parsers[ type || this.typeOf(obj) ];
type = typeof parser;
return type == 'function' ? parser.call( this, obj ) :
type == 'string' ? parser :
this.parsers.error;
},
typeOf:function( obj ) {
var type = typeof obj,
f = 'function';//we'll use it 3 times, save it
return type != 'object' && type != f ? type :
!obj ? 'null' :
obj.exec ? 'regexp' :// some browsers (FF) consider regexps functions
obj.getHours ? 'date' :
obj.scrollBy ? 'window' :
obj.nodeName == '#document' ? 'document' :
obj.nodeName ? 'node' :
obj.item ? 'nodelist' : // Safari reports nodelists as functions
obj.callee ? 'arguments' :
obj.call || obj.constructor != Array && //an array would also fall on this hack
(obj+'').indexOf(f) != -1 ? f : //IE reports functions like alert, as objects
'length' in obj ? 'array' :
type;
},
separator:function() {
return this.multiline ? this.HTML ? '<br />' : '\n' : this.HTML ? '&nbsp;' : ' ';
},
indent:function( extra ) {// extra can be a number, shortcut for increasing-calling-decreasing
if ( !this.multiline )
return '';
var chr = this.indentChar;
if ( this.HTML )
chr = chr.replace(/\t/g,' ').replace(/ /g,'&nbsp;');
return Array( this._depth_ + (extra||0) ).join(chr);
},
up:function( a ) {
this._depth_ += a || 1;
},
down:function( a ) {
this._depth_ -= a || 1;
},
setParser:function( name, parser ) {
this.parsers[name] = parser;
},
// The next 3 are exposed so you can use them
quote:quote,
literal:literal,
join:join,
//
_depth_: 1,
// This is the list of parsers, to modify them, use jsDump.setParser
parsers:{
window: '[Window]',
document: '[Document]',
error:'[ERROR]', //when no parser is found, shouldn't happen
unknown: '[Unknown]',
'null':'null',
undefined:'undefined',
'function':function( fn ) {
var ret = 'function',
name = 'name' in fn ? fn.name : (reName.exec(fn)||[])[1];//functions never have name in IE
if ( name )
ret += ' ' + name;
ret += '(';
ret = [ ret, this.parse( fn, 'functionArgs' ), '){'].join('');
return join( ret, this.parse(fn,'functionCode'), '}' );
},
array: array,
nodelist: array,
arguments: array,
object:function( map ) {
var ret = [ ];
this.up();
for ( var key in map )
ret.push( this.parse(key,'key') + ': ' + this.parse(map[key]) );
this.down();
return join( '{', ret, '}' );
},
node:function( node ) {
var open = this.HTML ? '&lt;' : '<',
close = this.HTML ? '&gt;' : '>';
var tag = node.nodeName.toLowerCase(),
ret = open + tag;
for ( var a in this.DOMAttrs ) {
var val = node[this.DOMAttrs[a]];
if ( val )
ret += ' ' + a + '=' + this.parse( val, 'attribute' );
}
return ret + close + open + '/' + tag + close;
},
functionArgs:function( fn ) {//function calls it internally, it's the arguments part of the function
var l = fn.length;
if ( !l ) return '';
var args = Array(l);
while ( l-- )
args[l] = String.fromCharCode(97+l);//97 is 'a'
return ' ' + args.join(', ') + ' ';
},
key:quote, //object calls it internally, the key part of an item in a map
functionCode:'[code]', //function calls it internally, it's the content of the function
attribute:quote, //node calls it internally, it's an html attribute value
string:quote,
date:quote,
regexp:literal, //regex
number:literal,
'boolean':literal
},
DOMAttrs:{//attributes to dump from nodes, name=>realName
id:'id',
name:'name',
'class':'className'
},
HTML:true,//if true, entities are escaped ( <, >, \t, space and \n )
indentChar:' ',//indentation unit
multiline:true //if true, items in a collection, are separated by a \n, else just a space.
};
return jsDump;
})();
})(this);

View File

@ -0,0 +1,84 @@
# ============================================================================
# Test basic discussion features (adding, replying, deleting)
# ============================================================================
#
# $ bin/robot-server plone.app.discussion.testing.PLONE_APP_DISCUSSION_ROBOT_TESTING
# $ bin/robot src/plone.app.discussion/src/plone/app/discussion/tests/robot/test_discussion.robot
#
# ============================================================================
*** Settings ***
Resource plone/app/robotframework/selenium.robot
Library Remote ${PLONE_URL}/RobotRemote
Test Setup Open test browser
Test Teardown Close all browsers
*** Test Cases ***
Enable Discussion on a Document
Given a logged-in Site Administrator
and a document
When I enable discussion on the document
Then I can see a comment form on the document
Add Comment to a Document
Given a logged-in Site Administrator
and a document with discussion enabled
When I add a comment
Then I can see the comment below the document
#Reply to a comment on a Document
# Given a logged-in Site Administrator
# and a document with discussion enabled
#Delete Comment from a Document
# Given a logged-in Site Administrator
# and a document with discussion enabled
*** Keywords ***
# Given
a logged-in Site Administrator
Enable autologin as Site Administrator
a document
Create content type=Document id=my-document title=My Document
a document with discussion enabled
a document
I enable discussion on the document
# When
I enable discussion on the document
Go To ${PLONE_URL}/my-document/edit
Wait until page contains Settings
Click Link Settings
Wait until element is visible name=form.widgets.IAllowDiscussion.allow_discussion:list
Select From List name=form.widgets.IAllowDiscussion.allow_discussion:list True
Click Button Save
I add a comment
Wait until page contains element id=form-widgets-comment-text
Input Text id=form-widgets-comment-text This is a comment
Click Button Comment
# Then
I can see a comment form on the document
Go To ${PLONE_URL}/my-document/view
Wait until page contains My Document
Page should contain Add comment
Page should contain element id=form-widgets-comment-text
I can see the comment below the document
Go To ${PLONE_URL}/my-document/view
Page should contain This is a comment

View File

@ -13,13 +13,12 @@ from Products.CMFCore.utils import getToolByName
from plone.app.testing import TEST_USER_ID, setRoles
from plone.app.discussion.testing import \
from plone.app.discussion.testing import (
PLONE_APP_DISCUSSION_INTEGRATION_TESTING
)
from plone.app.discussion.interfaces import IConversation
from plone.app.discussion.testing import COLLECTION_TYPE
class CatalogSetupTest(unittest.TestCase):
@ -29,16 +28,26 @@ class CatalogSetupTest(unittest.TestCase):
self.portal = self.layer['portal']
def test_catalog_installed(self):
self.assertTrue('total_comments' in
self.portal.portal_catalog.indexes())
self.assertTrue('commentators' in
self.portal.portal_catalog.indexes())
self.assertTrue('total_comments' in
self.portal.portal_catalog.schema())
self.assertTrue('in_response_to' in
self.portal.portal_catalog.schema())
self.assertTrue(
'total_comments' in
self.portal.portal_catalog.indexes()
)
self.assertTrue(
'commentators' in
self.portal.portal_catalog.indexes()
)
self.assertTrue(
'total_comments' in
self.portal.portal_catalog.schema()
)
self.assertTrue(
'in_response_to' in
self.portal.portal_catalog.schema()
)
def test_collection_criteria_installed(self):
if 'portal_atct' not in self.portal:
return
try:
self.portal.portal_atct.getIndex('commentators')
self.portal.portal_atct.getIndex('total_comments')
@ -54,10 +63,6 @@ class ConversationCatalogTest(unittest.TestCase):
def setUp(self):
self.portal = self.layer['portal']
setRoles(self.portal, TEST_USER_ID, ['Manager'])
self.portal.invokeFactory(id='doc1',
Title='Document 1',
type_name='Document')
self.catalog = getToolByName(self.portal, 'portal_catalog')
conversation = IConversation(self.portal.doc1)
comment1 = createObject('plone.Comment')
@ -72,8 +77,10 @@ class ConversationCatalogTest(unittest.TestCase):
self.comment_id = new_comment1_id
brains = self.catalog.searchResults(dict(
path={'query':
'/'.join(self.portal.doc1.getPhysicalPath())},
path={
'query':
'/'.join(self.portal.doc1.getPhysicalPath())
},
portal_type="Document"
))
self.conversation = conversation
@ -95,8 +102,10 @@ class ConversationCatalogTest(unittest.TestCase):
'++conversation++default/%s' % new_comment2_id)
comment2.reindexObject()
brains = self.catalog.searchResults(dict(
path={'query':
'/'.join(self.portal.doc1.getPhysicalPath())},
path={
'query':
'/'.join(self.portal.doc1.getPhysicalPath())
},
portal_type="Document"
))
doc1_brain = brains[0]
@ -104,8 +113,10 @@ class ConversationCatalogTest(unittest.TestCase):
def test_last_comment_date(self):
self.assertTrue('last_comment_date' in self.doc1_brain)
self.assertEqual(self.doc1_brain.last_comment_date,
datetime(2006, 9, 17, 14, 18, 12))
self.assertEqual(
self.doc1_brain.last_comment_date,
datetime(2006, 9, 17, 14, 18, 12)
)
# Add another comment and check if last comment date is updated.
comment2 = createObject('plone.Comment')
@ -119,31 +130,41 @@ class ConversationCatalogTest(unittest.TestCase):
'++conversation++default/%s' % new_comment2_id)
comment2.reindexObject()
brains = self.catalog.searchResults(dict(
path={'query':
'/'.join(self.portal.doc1.getPhysicalPath())},
path={
'query':
'/'.join(self.portal.doc1.getPhysicalPath())
},
portal_type="Document"
))
doc1_brain = brains[0]
self.assertEqual(doc1_brain.last_comment_date,
datetime(2009, 9, 17, 14, 18, 12))
self.assertEqual(
doc1_brain.last_comment_date,
datetime(2009, 9, 17, 14, 18, 12)
)
# Remove the comment again
del self.conversation[new_comment2_id]
brains = self.catalog.searchResults(dict(
path={'query':
'/'.join(self.portal.doc1.getPhysicalPath())},
path={
'query':
'/'.join(self.portal.doc1.getPhysicalPath())
},
portal_type="Document"
))
doc1_brain = brains[0]
self.assertEqual(doc1_brain.last_comment_date,
datetime(2006, 9, 17, 14, 18, 12))
self.assertEqual(
doc1_brain.last_comment_date,
datetime(2006, 9, 17, 14, 18, 12)
)
# remove all comments
del self.conversation[self.new_comment1_id]
brains = self.catalog.searchResults(dict(
path={'query':
'/'.join(self.portal.doc1.getPhysicalPath())},
path={
'query':
'/'.join(self.portal.doc1.getPhysicalPath())
},
portal_type="Document"
))
doc1_brain = brains[0]
@ -166,19 +187,23 @@ class ConversationCatalogTest(unittest.TestCase):
comment2.reindexObject()
brains = self.catalog.searchResults(dict(
path={'query':
'/'.join(self.portal.doc1.getPhysicalPath())},
path={
'query':
'/'.join(self.portal.doc1.getPhysicalPath())
},
portal_type="Document"
))
doc1_brain = brains[0]
self.assertEqual(doc1_brain.commentators, ('Emma', 'Jim'))
self.assertEqual(doc1_brain.commentators, ('Jim', 'Emma'))
# remove one comments
del self.conversation[new_comment2_id]
brains = self.catalog.searchResults(dict(
path={'query':
'/'.join(self.portal.doc1.getPhysicalPath())},
path={
'query':
'/'.join(self.portal.doc1.getPhysicalPath())
},
portal_type="Document"
))
doc1_brain = brains[0]
@ -187,8 +212,10 @@ class ConversationCatalogTest(unittest.TestCase):
# remove all comments
del self.conversation[self.new_comment1_id]
brains = self.catalog.searchResults(dict(
path={'query':
'/'.join(self.portal.doc1.getPhysicalPath())},
path={
'query':
'/'.join(self.portal.doc1.getPhysicalPath())
},
portal_type="Document"
))
doc1_brain = brains[0]
@ -196,8 +223,10 @@ class ConversationCatalogTest(unittest.TestCase):
def test_conversation_indexes_not_in_comments(self):
brains = self.catalog.searchResults(dict(
path={'query':
'/'.join(self.portal.doc1.getPhysicalPath())},
path={
'query':
'/'.join(self.portal.doc1.getPhysicalPath())
},
portal_type="Discussion Item"
))
comment1_brain = brains[0]
@ -205,6 +234,19 @@ class ConversationCatalogTest(unittest.TestCase):
self.assertEqual(comment1_brain.last_comment_date, None)
self.assertEqual(comment1_brain.total_comments, None)
def test_dont_index_private_commentators(self):
self.comment1.manage_permission("View", roles=tuple())
self.portal.doc1.reindexObject()
brains = self.catalog.searchResults(dict(
path={
'query':
'/'.join(self.portal.doc1.getPhysicalPath())
},
portal_type="Document"
))
doc1_brain = brains[0]
self.assertEqual(doc1_brain.commentators, ())
class CommentCatalogTest(unittest.TestCase):
@ -213,9 +255,6 @@ class CommentCatalogTest(unittest.TestCase):
def setUp(self):
self.portal = self.layer['portal']
setRoles(self.portal, TEST_USER_ID, ['Manager'])
self.portal.invokeFactory(id='doc1',
title='Document 1',
type_name='Document')
self.catalog = getToolByName(self.portal, 'portal_catalog')
conversation = IConversation(self.portal.doc1)
@ -232,8 +271,11 @@ class CommentCatalogTest(unittest.TestCase):
self.comment = self.portal.doc1.restrictedTraverse(
'++conversation++default/%s' % new_comment1_id)
brains = self.catalog.searchResults(dict(
path={'query':
'/'.join(self.comment.getPhysicalPath())}))
path={
'query':
'/'.join(self.comment.getPhysicalPath())
}
))
self.comment_brain = brains[0]
def test_title(self):
@ -248,8 +290,11 @@ class CommentCatalogTest(unittest.TestCase):
comment = self.portal.doc1.restrictedTraverse(
'++conversation++default/%s' % cid)
brains = self.catalog.searchResults(dict(
path={'query':
'/'.join(comment.getPhysicalPath())}))
path={
'query':
'/'.join(comment.getPhysicalPath())
}
))
comment_brain = brains[0]
self.assertEqual(comment_brain.Title, "Anonymous on Document 1")
@ -278,8 +323,11 @@ class CommentCatalogTest(unittest.TestCase):
# deleted.
del self.conversation[self.comment_id]
brains = self.catalog.searchResults(dict(
path={'query':
'/'.join(self.comment.getPhysicalPath())}))
path={
'query':
'/'.join(self.comment.getPhysicalPath())
}
))
self.assertEqual(len(brains), 0)
def test_remove_comments_when_content_object_is_removed(self):
@ -294,15 +342,21 @@ class CommentCatalogTest(unittest.TestCase):
def test_move_comments_when_content_object_is_moved(self):
# Create two folders and a content object with a comment
self.portal.invokeFactory(id='folder1',
self.portal.invokeFactory(
id='folder1',
title='Folder 1',
type_name='Folder')
self.portal.invokeFactory(id='folder2',
type_name='Folder'
)
self.portal.invokeFactory(
id='folder2',
title='Folder 2',
type_name='Folder')
self.portal.folder1.invokeFactory(id='moveme',
type_name='Folder'
)
self.portal.folder1.invokeFactory(
id='moveme',
title='Move Me',
type_name='Document')
type_name='Document'
)
conversation = IConversation(self.portal.folder1.moveme)
comment = createObject('plone.Comment')
comment_id = conversation.addComment(comment)
@ -327,10 +381,11 @@ class CommentCatalogTest(unittest.TestCase):
}
))
self.assertEqual(len(brains), 1)
self.assertEqual(brains[0].getPath(),
self.assertEqual(
brains[0].getPath(),
'/plone/folder2/moveme/++conversation++default/' +
str(comment_id))
str(comment_id)
)
def test_move_upper_level_folder(self):
# create a folder with a nested structure
@ -348,7 +403,9 @@ class CommentCatalogTest(unittest.TestCase):
type_name='Folder')
# create comment on my-document
conversation = IConversation(self.portal.sourcefolder.moveme.mydocument)
conversation = IConversation(
self.portal.sourcefolder.moveme.mydocument
)
comment = createObject('plone.Comment')
comment_id = conversation.addComment(comment)
@ -372,9 +429,11 @@ class CommentCatalogTest(unittest.TestCase):
path={'query': '/plone/targetfolder/moveme'}
))
self.assertEqual(len(brains), 1)
self.assertEqual(brains[0].getPath(),
self.assertEqual(
brains[0].getPath(),
'/plone/targetfolder/moveme/mydocument/++conversation++default/' +
str(comment_id))
str(comment_id)
)
def test_update_comments_when_content_object_is_renamed(self):
# We need to commit here so that _p_jar isn't None and move will work
@ -385,11 +444,16 @@ class CommentCatalogTest(unittest.TestCase):
brains = self.catalog.searchResults(
portal_type='Discussion Item')
self.assertEqual(len(brains), 1)
self.assertEqual(brains[0].getPath(),
self.assertEqual(
brains[0].getPath(),
'/plone/doc2/++conversation++default/' +
str(self.comment_id))
str(self.comment_id)
)
def test_clear_and_rebuild_catalog(self):
brains = self.catalog.searchResults({'portal_type': 'Discussion Item'})
self.assertTrue(brains)
# Clear and rebuild catalog
self.catalog.clearFindAndRebuild()
@ -398,9 +462,11 @@ class CommentCatalogTest(unittest.TestCase):
self.assertTrue(brains)
comment_brain = brains[0]
self.assertEqual(comment_brain.Title, u'Jim on Document 1')
self.assertEqual(comment_brain.getPath(),
self.assertEqual(
comment_brain.getPath(),
'/plone/doc1/++conversation++default/' +
str(self.comment_id))
str(self.comment_id)
)
def test_clear_and_rebuild_catalog_for_nested_comments(self):
@ -458,31 +524,6 @@ class CommentCatalogTest(unittest.TestCase):
self.assertTrue(brains)
self.assertEqual(len(brains), 6)
def test_collection(self):
if COLLECTION_TYPE == "Topic":
self.portal.invokeFactory('Topic', id='topic')
topic = self.portal.topic
crit = topic.addCriterion('Type', 'ATSimpleStringCriterion')
crit.setValue('Comment')
query = topic.buildQuery()
self.assertEqual(len(query), 1)
self.assertEqual(query['Type'], 'Comment')
self.assertEqual(len(topic.queryCatalog()), 1)
else:
self.portal.invokeFactory('Collection', id='collection')
collection = self.portal.collection
collection.query = [{
'i': 'Type',
'o': 'plone.app.querystring.operation.string.is',
'v': 'Comment',
}]
self.assertEqual(len(collection.results()), 1)
self.assertEqual(collection.results()[0].text, 'Comment text')
self.assertEqual(collection.results()[0].creator, 'jim')
self.assertEqual(collection.results()[0].author_name, 'Jim')
class NoConversationCatalogTest(unittest.TestCase):
@ -491,17 +532,16 @@ class NoConversationCatalogTest(unittest.TestCase):
def setUp(self):
self.portal = self.layer['portal']
setRoles(self.portal, TEST_USER_ID, ['Manager'])
self.portal.invokeFactory(id='doc1',
Title='Document 1',
type_name='Document')
self.catalog = getToolByName(self.portal, 'portal_catalog')
conversation = IConversation(self.portal.doc1)
brains = self.catalog.searchResults(dict(
path={'query':
'/'.join(self.portal.doc1.getPhysicalPath())},
path={
'query':
'/'.join(self.portal.doc1.getPhysicalPath())
},
portal_type="Document"
))
self.conversation = conversation
@ -513,9 +553,7 @@ class NoConversationCatalogTest(unittest.TestCase):
self.assertEqual(self.doc1_brain.total_comments, 0)
# Make sure no conversation has been created
self.assertTrue('plone.app.discussion:conversation' not in
IAnnotations(self.portal.doc1))
def test_suite():
return unittest.defaultTestLoader.loadTestsFromName(__name__)
self.assertTrue(
'plone.app.discussion:conversation' not in
IAnnotations(self.portal.doc1)
)

View File

@ -34,9 +34,6 @@ class CommentTest(unittest.TestCase):
self.request = self.layer['request']
setRoles(self.portal, TEST_USER_ID, ['Manager'])
self.portal.invokeFactory(id='doc1',
title='Document 1',
type_name='Document')
self.catalog = getToolByName(self.portal, 'portal_catalog')
self.document_brain = self.catalog.searchResults(
portal_type='Document')[0]
@ -74,7 +71,8 @@ class CommentTest(unittest.TestCase):
comment1 = createObject('plone.Comment')
conversation.addComment(comment1)
comment_brain = self.catalog.searchResults(
portal_type='Discussion Item')[0]
portal_type='Discussion Item'
)[0]
self.assertTrue(comment_brain.UID)
def test_uid_is_unique(self):
@ -84,7 +82,8 @@ class CommentTest(unittest.TestCase):
comment2 = createObject('plone.Comment')
conversation.addComment(comment2)
brains = self.catalog.searchResults(
portal_type='Discussion Item')
portal_type='Discussion Item'
)
self.assertNotEqual(brains[0].UID, brains[1].UID)
def test_comment_uid_differs_from_content_uid(self):
@ -92,7 +91,8 @@ class CommentTest(unittest.TestCase):
comment1 = createObject('plone.Comment')
conversation.addComment(comment1)
comment_brain = self.catalog.searchResults(
portal_type='Discussion Item')[0]
portal_type='Discussion Item'
)[0]
self.assertNotEqual(self.document_brain.UID, comment_brain.UID)
def test_title(self):
@ -109,20 +109,44 @@ class CommentTest(unittest.TestCase):
self.assertEqual("Anonymous on Document 1", comment1.Title())
def test_title_special_characters(self):
self.portal.invokeFactory(id='doc_sp_chars',
self.portal.invokeFactory(
id='doc_sp_chars',
title=u'Document äüö',
type_name='Document')
type_name='Document'
)
conversation = IConversation(self.portal.doc_sp_chars)
comment1 = createObject('plone.Comment')
comment1.author_name = u"Tarek Ziadé"
conversation.addComment(comment1)
self.assertEqual(u"Tarek Ziadé on Document äüö", comment1.Title())
def test_title_special_characters_utf8(self):
self.portal.invokeFactory(
id='doc_sp_chars_utf8',
title='Document ëïû',
type_name='Document'
)
conversation = IConversation(self.portal.doc_sp_chars_utf8)
comment1 = createObject('plone.Comment')
comment1.author_name = "Hüüb Bôûmä"
conversation.addComment(comment1)
self.assertEqual(u"Hüüb Bôûmä on Document ëïû", comment1.Title())
def test_creator(self):
comment1 = createObject('plone.Comment')
comment1.creator = "jim"
self.assertEqual("jim", comment1.Creator())
def test_creator_author_name(self):
comment1 = createObject('plone.Comment')
comment1.author_name = "joey"
self.assertEqual("joey", comment1.Creator())
def test_owner(self):
comment1 = createObject('plone.Comment')
self.assertEqual((['plone', 'acl_users'], TEST_USER_ID),
comment1.getOwnerTuple())
def test_type(self):
comment1 = createObject('plone.Comment')
self.assertEqual(comment1.Type(), 'Comment')
@ -136,41 +160,53 @@ class CommentTest(unittest.TestCase):
comment1.text = """First paragraph
Second paragraph"""
self.assertEqual(comment1.getText(),
"<p>First paragraph<br /><br /> Second paragraph</p>")
self.assertEqual(
comment1.getText(),
"<p>First paragraph<br /><br /> Second paragraph</p>"
)
def test_getText_escapes_HTML(self):
comment1 = createObject('plone.Comment')
comment1.text = """<b>Got HTML?</b>"""
self.assertEqual(comment1.getText(),
"<p>&lt;b&gt;Got HTML?&lt;/b&gt;</p>")
self.assertEqual(
comment1.getText(),
"<p>&lt;b&gt;Got HTML?&lt;/b&gt;</p>"
)
def test_getText_with_non_ascii_characters(self):
comment1 = createObject('plone.Comment')
comment1.text = u"""Umlaute sind ä, ö und ü."""
self.assertEqual(comment1.getText(),
'<p>Umlaute sind \xc3\xa4, \xc3\xb6 und \xc3\xbc.</p>')
self.assertEqual(
comment1.getText(),
'<p>Umlaute sind \xc3\xa4, \xc3\xb6 und \xc3\xbc.</p>'
)
def test_getText_doesnt_link(self):
comment1 = createObject('plone.Comment')
comment1.text = "Go to http://www.plone.org"
self.assertEqual(comment1.getText(),
"<p>Go to http://www.plone.org</p>")
self.assertEqual(
comment1.getText(),
"<p>Go to http://www.plone.org</p>"
)
def test_getText_uses_comment_mime_type(self):
comment1 = createObject('plone.Comment')
comment1.text = "Go to http://www.plone.org"
comment1.mime_type = 'text/x-web-intelligent'
self.assertEqual(comment1.getText(),
self.assertEqual(
comment1.getText(),
'Go to <a href="http://www.plone.org" ' +
'rel="nofollow">http://www.plone.org</a>')
'rel="nofollow">http://www.plone.org</a>'
)
def test_getText_uses_comment_mime_type_html(self):
comment1 = createObject('plone.Comment')
comment1.text = 'Go to <a href="http://www.plone.org">plone.org</a>'
comment1.mime_type = 'text/html'
self.assertEqual(comment1.getText(),
'Go to <a href="http://www.plone.org">plone.org</a>')
self.assertEqual(
comment1.getText(),
'Go to <a href="http://www.plone.org">plone.org</a>'
)
def test_getText_w_custom_targetMimetype(self):
comment1 = createObject('plone.Comment')
@ -202,19 +238,28 @@ class CommentTest(unittest.TestCase):
'++conversation++default/%s' % new_comment1_id)
self.assertTrue(IComment.providedBy(comment))
self.assertEqual(('', 'plone', 'doc1', '++conversation++default',
str(new_comment1_id)), comment.getPhysicalPath())
self.assertEqual('http://nohost/plone/doc1/++conversation++default/' +
str(new_comment1_id), comment.absolute_url())
self.assertEqual(
(
'', 'plone', 'doc1', '++conversation++default',
str(new_comment1_id)
),
comment.getPhysicalPath()
)
self.assertEqual(
'http://nohost/plone/doc1/++conversation++default/' +
str(new_comment1_id), comment.absolute_url()
)
def test_view_blob_types(self):
"""
Make sure that traversal to images/files redirects to the
version of the url with a /view in it.
"""
self.portal.invokeFactory(id='image1',
self.portal.invokeFactory(
id='image1',
title='Image',
type_name='Image')
type_name='Image'
)
conversation = IConversation(self.portal.image1)
comment1 = createObject('plone.Comment')
@ -246,18 +291,26 @@ class CommentTest(unittest.TestCase):
self.assertEqual(('comment_review_workflow',), chain)
# Ensure the initial state was entered and recorded
self.assertEqual(1,
len(comment.workflow_history['comment_review_workflow']))
self.assertEqual(None,
comment.workflow_history['comment_review_workflow'][0]['action'])
self.assertEqual('pending',
self.portal.portal_workflow.getInfoFor(comment, 'review_state'))
self.assertEqual(
1,
len(comment.workflow_history['comment_review_workflow'])
)
self.assertEqual(
None,
comment.workflow_history['comment_review_workflow'][0]['action']
)
self.assertEqual(
'pending',
self.portal.portal_workflow.getInfoFor(comment, 'review_state')
)
def test_fti(self):
# test that we can look up an FTI for Discussion Item
self.assertTrue("Discussion Item" in
self.portal.portal_types.objectIds())
self.assertTrue(
"Discussion Item" in
self.portal.portal_types.objectIds()
)
comment1 = createObject('plone.Comment')
@ -302,9 +355,6 @@ class RepliesTest(unittest.TestCase):
def setUp(self):
self.portal = self.layer['portal']
setRoles(self.portal, TEST_USER_ID, ['Manager'])
self.portal.invokeFactory(id='doc1',
title='Document 1',
type_name='Document')
def test_add_comment(self):
# Add comments to a CommentReplies adapter
@ -373,7 +423,7 @@ class RepliesTest(unittest.TestCase):
self.assertEqual(len(replies), 0)
# Make sure the first comment is still in the conversation
self.assertEqual(conversation.total_comments, 1)
self.assertEqual(conversation.total_comments(), 1)
def test_traversal(self):
# Create a nested structure of comment replies and check the traversal
@ -399,7 +449,8 @@ class RepliesTest(unittest.TestCase):
replies = IReplies(comment)
new_re_id = replies.addComment(re_comment)
re_comment = self.portal.doc1.restrictedTraverse(
'++conversation++default/%s' % new_re_id)
'++conversation++default/%s' % new_re_id
)
# Add a reply to the reply
re_re_comment = createObject('plone.Comment')
@ -407,7 +458,8 @@ class RepliesTest(unittest.TestCase):
replies = IReplies(re_comment)
new_re_re_id = replies.addComment(re_re_comment)
re_re_comment = self.portal.doc1.restrictedTraverse(
'++conversation++default/%s' % new_re_re_id)
'++conversation++default/%s' % new_re_re_id
)
# Add a reply to the replies reply
re_re_re_comment = createObject('plone.Comment')
@ -417,25 +469,44 @@ class RepliesTest(unittest.TestCase):
re_re_re_comment = self.portal.doc1.restrictedTraverse(
'++conversation++default/%s' % new_re_re_re_id)
self.assertEqual(('', 'plone', 'doc1', '++conversation++default',
str(new_id)), comment.getPhysicalPath())
self.assertEqual('http://nohost/plone/doc1/++conversation++default/' +
str(new_id), comment.absolute_url())
self.assertEqual(('', 'plone', 'doc1', '++conversation++default',
str(new_re_id)), re_comment.getPhysicalPath())
self.assertEqual('http://nohost/plone/doc1/++conversation++default/' +
str(new_re_id), re_comment.absolute_url())
self.assertEqual(('', 'plone', 'doc1', '++conversation++default',
str(new_re_re_id)), re_re_comment.getPhysicalPath())
self.assertEqual('http://nohost/plone/doc1/++conversation++default/' +
str(new_re_re_id), re_re_comment.absolute_url())
self.assertEqual(('', 'plone', 'doc1', '++conversation++default',
str(new_re_re_re_id)),
re_re_re_comment.getPhysicalPath())
self.assertEqual('http://nohost/plone/doc1/++conversation++default/' +
self.assertEqual(
('', 'plone', 'doc1', '++conversation++default', str(new_id)),
comment.getPhysicalPath()
)
self.assertEqual(
'http://nohost/plone/doc1/++conversation++default/' +
str(new_id), comment.absolute_url()
)
self.assertEqual(
('', 'plone', 'doc1', '++conversation++default', str(new_re_id)),
re_comment.getPhysicalPath()
)
self.assertEqual(
'http://nohost/plone/doc1/++conversation++default/' +
str(new_re_id),
re_comment.absolute_url()
)
self.assertEqual(
(
'', 'plone', 'doc1', '++conversation++default',
str(new_re_re_id)
),
re_re_comment.getPhysicalPath()
)
self.assertEqual(
'http://nohost/plone/doc1/++conversation++default/' +
str(new_re_re_id),
re_re_comment.absolute_url()
)
self.assertEqual(
(
'', 'plone', 'doc1', '++conversation++default',
str(new_re_re_re_id)
),
re_re_re_comment.getPhysicalPath()
)
self.assertEqual(
'http://nohost/plone/doc1/++conversation++default/' +
str(new_re_re_re_id),
re_re_re_comment.absolute_url())
def test_suite():
return unittest.defaultTestLoader.loadTestsFromName(__name__)
re_re_re_comment.absolute_url()
)

View File

@ -26,18 +26,21 @@ from Products.CMFCore.utils import getToolByName
from Products.CMFPlone.tests import dummy
from plone.app.testing import TEST_USER_ID, setRoles
from plone.app.testing import TEST_USER_ID, TEST_USER_NAME, setRoles
from plone.app.testing import logout
from plone.app.testing import login
from plone.app.discussion.browser.comments import CommentsViewlet
from plone.app.discussion.browser.comments import CommentForm
from plone.app.discussion.browser.comment import EditCommentForm
from plone.app.discussion import interfaces
from plone.app.discussion.interfaces import IConversation
from plone.app.discussion.testing import \
from plone.app.discussion.testing import (
PLONE_APP_DISCUSSION_INTEGRATION_TESTING
)
from plone.app.discussion.interfaces import IDiscussionSettings
from plone.app.discussion.interfaces import IConversation
class TestCommentForm(unittest.TestCase):
@ -52,14 +55,13 @@ class TestCommentForm(unittest.TestCase):
self.folder = self.portal['test-folder']
interface.alsoProvides(
self.portal.REQUEST, interfaces.IDiscussionLayer)
self.portal.REQUEST,
interfaces.IDiscussionLayer,
)
typetool = self.portal.portal_types
typetool.constructContent('Document', self.portal, 'doc1')
self.discussionTool = getToolByName(self.portal,
'portal_discussion',
None)
self.discussionTool.overrideDiscussionFor(self.portal.doc1, False)
wftool = getToolByName(self.portal, "portal_workflow")
wftool.doActionFor(self.portal.doc1, action='publish')
self.portal.doc1.allow_discussion = True
self.membershipTool = getToolByName(self.folder, 'portal_membership')
self.memberdata = self.portal.portal_memberdata
self.context = getattr(self.portal, 'doc1')
@ -74,7 +76,7 @@ class TestCommentForm(unittest.TestCase):
"""
# Allow discussion
self.discussionTool.overrideDiscussionFor(self.portal.doc1, True)
self.portal.doc1.allow_discussion = True
self.viewlet = CommentsViewlet(self.context, self.request, None, None)
def make_request(form={}):
@ -84,16 +86,20 @@ class TestCommentForm(unittest.TestCase):
alsoProvides(request, IAttributeAnnotatable)
return request
provideAdapter(adapts=(Interface, IBrowserRequest),
provideAdapter(
adapts=(Interface, IBrowserRequest),
provides=Interface,
factory=CommentForm,
name=u"comment-form")
name=u"comment-form"
)
# The form should return an error if the comment text field is empty
request = make_request(form={})
commentForm = getMultiAdapter((self.context, request),
name=u"comment-form")
commentForm = getMultiAdapter(
(self.context, request),
name=u"comment-form"
)
commentForm.update()
data, errors = commentForm.extractData() # pylint: disable-msg=W0612
@ -104,16 +110,216 @@ class TestCommentForm(unittest.TestCase):
# filled out
request = make_request(form={'form.widgets.text': u'bar'})
commentForm = getMultiAdapter((self.context, request),
name=u"comment-form")
commentForm = getMultiAdapter(
(self.context, request),
name=u"comment-form"
)
commentForm.update()
data, errors = commentForm.extractData() # pylint: disable-msg=W0612
self.assertEqual(len(errors), 0)
self.assertFalse(commentForm.handleComment(commentForm, "foo"))
comments = IConversation(commentForm.context).getComments()
comments = [comment for comment in comments] # consume itertor
self.assertEqual(len(comments), 1)
for comment in comments:
self.assertEqual(comment.text, u"bar")
self.assertEqual(comment.creator, "test_user_1_")
self.assertEqual(comment.getOwner().getUserName(), "test-user")
local_roles = comment.get_local_roles()
self.assertEqual(len(local_roles), 1)
userid, roles = local_roles[0]
self.assertEqual(userid, 'test_user_1_')
self.assertEqual(len(roles), 1)
self.assertEqual(roles[0], 'Owner')
def test_edit_comment(self):
"""Edit a comment as logged-in user.
"""
# Allow discussion
self.portal.doc1.allow_discussion = True
self.viewlet = CommentsViewlet(self.context, self.request, None, None)
def make_request(form={}):
request = TestRequest()
request.form.update(form)
alsoProvides(request, IFormLayer)
alsoProvides(request, IAttributeAnnotatable)
return request
provideAdapter(
adapts=(Interface, IBrowserRequest),
provides=Interface,
factory=CommentForm,
name=u"comment-form"
)
provideAdapter(
adapts=(Interface, IBrowserRequest),
provides=Interface,
factory=EditCommentForm,
name=u"edit-comment-form"
)
# The form is submitted successfully, if the required text field is
# filled out
request = make_request(form={'form.widgets.text': u'bar'})
commentForm = getMultiAdapter(
(self.context, request),
name=u"comment-form"
)
commentForm.update()
data, errors = commentForm.extractData() # pylint: disable-msg=W0612
self.assertEqual(len(errors), 0)
self.assertFalse(commentForm.handleComment(commentForm, "foo"))
# Edit the last comment
conversation = IConversation(self.context)
comment = [x for x in conversation.getComments()][-1]
request = make_request(form={'form.widgets.text': u'foobar'})
editForm = getMultiAdapter(
(comment, request),
name=u"edit-comment-form"
)
editForm.update()
data, errors = editForm.extractData() # pylint: disable-msg=W0612
self.assertEqual(len(errors), 0)
self.assertFalse(editForm.handleComment(editForm, "foo"))
comment = [x for x in conversation.getComments()][-1]
self.assertEquals(comment.text, u"foobar")
comments = IConversation(commentForm.context).getComments()
comments = [comment for comment in comments] # consume itertor
self.assertEqual(len(comments), 1)
for comment in comments:
self.assertEqual(comment.text, u"foobar")
self.assertEqual(comment.creator, "test_user_1_")
self.assertEqual(comment.getOwner().getUserName(), "test-user")
local_roles = comment.get_local_roles()
self.assertEqual(len(local_roles), 1)
userid, roles = local_roles[0]
self.assertEqual(userid, 'test_user_1_')
self.assertEqual(len(roles), 1)
self.assertEqual(roles[0], 'Owner')
def test_delete_comment(self):
"""Delete a comment as logged-in user.
"""
# Allow discussion
self.portal.doc1.allow_discussion = True
self.viewlet = CommentsViewlet(self.context, self.request, None, None)
def make_request(form={}):
request = TestRequest()
request.form.update(form)
alsoProvides(request, IFormLayer)
alsoProvides(request, IAttributeAnnotatable)
return request
provideAdapter(
adapts=(Interface, IBrowserRequest),
provides=Interface,
factory=CommentForm,
name=u"comment-form"
)
# The form is submitted successfully, if the required text field is
# filled out
form_request = make_request(form={'form.widgets.text': u'bar'})
commentForm = getMultiAdapter(
(self.context, form_request),
name=u"comment-form"
)
commentForm.update()
data, errors = commentForm.extractData() # pylint: disable-msg=W0612
self.assertEqual(len(errors), 0)
self.assertFalse(commentForm.handleComment(commentForm, "foo"))
# Delete the last comment
conversation = IConversation(self.context)
comment = [x for x in conversation.getComments()][-1]
deleteView = getMultiAdapter(
(comment, self.request),
name=u"moderate-delete-comment"
)
# try to delete last comment without "Delete comments" permission
setRoles(self.portal, TEST_USER_ID, ['Member'])
self.assertRaises(Unauthorized, comment.restrictedTraverse, "@@moderate-delete-comment")
deleteView()
self.assertEqual(1, len([x for x in conversation.getComments()]))
# try to delete last comment with "Delete comments" permission
setRoles(self.portal, TEST_USER_ID, ['Reviewer'])
deleteView()
self.assertEqual(0, len([x for x in conversation.getComments()]))
setRoles(self.portal, TEST_USER_ID, ['Manager'])
def test_delete_own_comment(self):
"""Delete own comment as logged-in user.
"""
# Allow discussion
self.portal.doc1.allow_discussion = True
self.viewlet = CommentsViewlet(self.context, self.request, None, None)
def make_request(form={}):
request = TestRequest()
request.form.update(form)
alsoProvides(request, IFormLayer)
alsoProvides(request, IAttributeAnnotatable)
return request
provideAdapter(
adapts=(Interface, IBrowserRequest),
provides=Interface,
factory=CommentForm,
name=u"comment-form"
)
# The form is submitted successfully, if the required text field is
# filled out
form_request = make_request(form={'form.widgets.text': u'bar'})
commentForm = getMultiAdapter(
(self.context, form_request),
name=u"comment-form"
)
commentForm.update()
data, errors = commentForm.extractData() # pylint: disable-msg=W0612
self.assertEqual(len(errors), 0)
self.assertFalse(commentForm.handleComment(commentForm, "foo"))
# Delete the last comment
conversation = IConversation(self.context)
comment = [x for x in conversation.getComments()][-1]
deleteView = getMultiAdapter(
(comment, self.request),
name=u"delete-own-comment"
)
# try to delete last comment with johndoe
setRoles(self.portal, 'johndoe', ['Member'])
login(self.portal, 'johndoe')
self.assertRaises(Unauthorized, comment.restrictedTraverse, "@@delete-own-comment")
self.assertEqual(1, len([x for x in conversation.getComments()]))
# try to delete last comment with the same user that created it
login(self.portal, TEST_USER_NAME)
setRoles(self.portal, TEST_USER_ID, ['Member'])
deleteView()
self.assertEqual(0, len([x for x in conversation.getComments()]))
def test_add_anonymous_comment(self):
self.discussionTool.overrideDiscussionFor(self.portal.doc1, True)
self.portal.doc1.allow_discussion = True
self.viewlet = CommentsViewlet(self.context, self.request, None, None)
@ -137,22 +343,39 @@ class TestCommentForm(unittest.TestCase):
name=u"comment-form")
# Post an anonymous comment and provide a name
request = make_request(form={'form.widgets.name': u'john doe',
'form.widgets.text': u'bar'})
request = make_request(form={
'form.widgets.name': u'john doe',
'form.widgets.text': u'bar'
})
commentForm = getMultiAdapter((self.context, request),
name=u"comment-form")
commentForm = getMultiAdapter(
(self.context, request),
name=u"comment-form"
)
commentForm.update()
data, errors = commentForm.extractData() # pylint: disable-msg=W0612
self.assertEqual(len(errors), 0)
self.assertFalse(commentForm.handleComment(commentForm, "action"))
comments = IConversation(commentForm.context).getComments()
comments = [comment for comment in comments] # consume itertor
self.assertEqual(len(comments), 1)
for comment in IConversation(commentForm.context).getComments():
self.assertEqual(comment.text, u"bar")
self.assertIsNone(comment.creator)
roles = comment.get_local_roles()
self.assertEqual(len(roles), 0)
def test_can_not_add_comments_if_discussion_is_not_allowed(self):
"""Make sure that comments can't be posted if discussion is disabled.
"""
# Discussion is disabled by default
# Disable discussion
registry = queryUtility(IRegistry)
settings = registry.forInterface(IDiscussionSettings)
settings.globally_enabled = False
def make_request(form={}):
request = TestRequest()
@ -168,14 +391,17 @@ class TestCommentForm(unittest.TestCase):
request = make_request(form={'form.widgets.text': u'bar'})
commentForm = getMultiAdapter((self.context, request),
name=u"comment-form")
commentForm = getMultiAdapter(
(self.context, request),
name=u"comment-form"
)
commentForm.update()
data, errors = commentForm.extractData() # pylint: disable-msg=W0612
# No form errors, but raise unauthorized because discussion is not
# allowed
self.assertEqual(len(errors), 0)
self.assertRaises(Unauthorized,
commentForm.handleComment,
commentForm,
@ -210,10 +436,12 @@ class TestCommentForm(unittest.TestCase):
data, errors = commentForm.extractData() # pylint: disable-msg=W0612
self.assertEqual(len(errors), 0)
self.assertRaises(Unauthorized,
self.assertRaises(
Unauthorized,
commentForm.handleComment,
commentForm,
"foo")
"foo"
)
class TestCommentsViewlet(unittest.TestCase):
@ -227,16 +455,13 @@ class TestCommentsViewlet(unittest.TestCase):
self.portal.invokeFactory('Folder', 'test-folder')
self.folder = self.portal['test-folder']
interface.alsoProvides(
self.request, interfaces.IDiscussionLayer)
self.request,
interfaces.IDiscussionLayer
)
self.workflowTool = getToolByName(self.portal, 'portal_workflow')
self.workflowTool.setDefaultChain('one_state_workflow')
typetool = self.portal.portal_types
typetool.constructContent('Document', self.portal, 'doc1')
self.portal_discussion = getToolByName(self.portal,
'portal_discussion',
None)
self.membershipTool = getToolByName(self.folder, 'portal_membership')
self.memberdata = self.portal.portal_memberdata
context = getattr(self.portal, 'doc1')
@ -286,8 +511,7 @@ class TestCommentsViewlet(unittest.TestCase):
# By default, discussion is disabled
self.assertFalse(self.viewlet.is_discussion_allowed())
# Enable discussion
portal_discussion = getToolByName(self.portal, 'portal_discussion')
portal_discussion.overrideDiscussionFor(self.portal.doc1, True)
self.portal.doc1.allow_discussion = True
# Test if discussion has been enabled
self.assertTrue(self.viewlet.is_discussion_allowed())
@ -310,7 +534,8 @@ class TestCommentsViewlet(unittest.TestCase):
self.viewlet.comment_transform_message(),
"You can add a comment by filling out the form below. " +
"Plain text formatting. Web and email addresses are transformed " +
"into clickable links.")
"into clickable links."
)
# Enable moderation workflow
self.workflowTool.setChainForPortalTypes(
@ -346,6 +571,14 @@ class TestCommentsViewlet(unittest.TestCase):
replies.next()
self.assertRaises(StopIteration, replies.next)
def test_get_replies_on_non_annotatable_object(self):
context = self.portal.MailHost # the mail host is not annotatable
viewlet = CommentsViewlet(context, self.request, None, None)
replies = viewlet.get_replies()
self.assertEqual(len(tuple(replies)), 0)
replies = viewlet.get_replies()
self.assertRaises(StopIteration, replies.next)
def test_get_replies_with_workflow_actions(self):
self.assertFalse(self.viewlet.get_replies(workflow_actions=True))
comment = createObject('plone.Comment')
@ -353,19 +586,26 @@ class TestCommentsViewlet(unittest.TestCase):
conversation = IConversation(self.portal.doc1)
c1 = conversation.addComment(comment)
self.assertEqual(
len(tuple(self.viewlet.get_replies(workflow_actions=True))), 1)
len(tuple(self.viewlet.get_replies(workflow_actions=True))),
1
)
# Enable moderation workflow
self.workflowTool.setChainForPortalTypes(
('Discussion Item',),
('comment_review_workflow,'))
('comment_review_workflow,')
)
# Check if workflow actions are available
reply = self.viewlet.get_replies(workflow_actions=True).next()
self.assertTrue('actions' in reply)
self.assertEqual(reply['actions'][0]['id'],
'publish')
self.assertEqual(reply['actions'][0]['url'],
self.assertEqual(
reply['actions'][0]['id'],
'publish'
)
self.assertEqual(
reply['actions'][0]['url'],
'http://nohost/plone/doc1/++conversation++default/%s' % int(c1) +
'/content_status_modify?workflow_action=publish')
'/content_status_modify?workflow_action=publish'
)
def test_get_commenter_home_url(self):
comment = createObject('plone.Comment')
@ -373,8 +613,10 @@ class TestCommentsViewlet(unittest.TestCase):
IConversation(self.portal.doc1)
portal_membership = getToolByName(self.portal, 'portal_membership')
m = portal_membership.getAuthenticatedMember()
self.assertEqual(self.viewlet.get_commenter_home_url(m.getUserName()),
'http://nohost/plone/author/test-user')
self.assertEqual(
self.viewlet.get_commenter_home_url(m.getUserName()),
'http://nohost/plone/author/test-user'
)
def test_get_commenter_home_url_is_none(self):
self.assertFalse(self.viewlet.get_commenter_home_url())
@ -383,13 +625,19 @@ class TestCommentsViewlet(unittest.TestCase):
# Add a user with a member image
self.membershipTool.addMember('jim', 'Jim', ['Member'], [])
self.memberdata._setPortrait(Image(id='jim',
self.memberdata._setPortrait(Image(
id='jim',
file=dummy.File(),
title=''), 'jim')
self.assertEqual(self.memberdata._getPortrait('jim').getId(),
'jim')
self.assertEqual(self.memberdata._getPortrait('jim').meta_type,
'Image')
title=''
), 'jim')
self.assertEqual(
self.memberdata._getPortrait('jim').getId(),
'jim'
)
self.assertEqual(
self.memberdata._getPortrait('jim').meta_type,
'Image'
)
# Add a conversation with a comment
conversation = IConversation(self.portal.doc1)
@ -404,12 +652,20 @@ class TestCommentsViewlet(unittest.TestCase):
portrait_url = self.viewlet.get_commenter_portrait('jim')
# Check if the correct member image URL is returned
self.assertEqual(portrait_url,
'http://nohost/plone/portal_memberdata/portraits/jim')
self.assertEqual(
portrait_url,
'http://nohost/plone/portal_memberdata/portraits/jim'
)
def test_get_commenter_portrait_is_none(self):
self.assertEqual(self.viewlet.get_commenter_portrait(),
'defaultUser.gif')
self.assertTrue(
self.viewlet.get_commenter_portrait() in (
'defaultUser.png',
'defaultUser.gif',
)
)
def test_get_commenter_portrait_without_userimage(self):
@ -431,25 +687,32 @@ class TestCommentsViewlet(unittest.TestCase):
# Check if the correct default member image URL is returned.
# Note that Products.PlonePAS 4.0.5 and later have .png and
# earlier versions have .gif.
self.assertTrue(portrait_url in
('http://nohost/plone/defaultUser.png',
'http://nohost/plone/defaultUser.gif'))
self.assertTrue(
portrait_url in (
'http://nohost/plone/defaultUser.png',
'http://nohost/plone/defaultUser.gif'
)
)
def test_anonymous_discussion_allowed(self):
# Anonymous discussion is not allowed by default
self.assertFalse(self.viewlet.anonymous_discussion_allowed())
# Allow anonymous discussion
registry = queryUtility(IRegistry)
registry['plone.app.discussion.interfaces.IDiscussionSettings.' +
'anonymous_comments'] = True
registry[
'plone.app.discussion.interfaces.IDiscussionSettings.' +
'anonymous_comments'
] = True
# Test if anonymous discussion is allowed for the viewlet
self.assertTrue(self.viewlet.anonymous_discussion_allowed())
def test_show_commenter_image(self):
self.assertTrue(self.viewlet.show_commenter_image())
registry = queryUtility(IRegistry)
registry['plone.app.discussion.interfaces.IDiscussionSettings.' +
'show_commenter_image'] = False
registry[
'plone.app.discussion.interfaces.IDiscussionSettings.' +
'show_commenter_image'
] = False
self.assertFalse(self.viewlet.show_commenter_image())
def test_is_anonymous(self):
@ -459,8 +722,10 @@ class TestCommentsViewlet(unittest.TestCase):
def test_login_action(self):
self.viewlet.update()
self.assertEqual(self.viewlet.login_action(),
'http://nohost/plone/login_form?came_from=http%3A//nohost')
self.assertEqual(
self.viewlet.login_action(),
'http://nohost/plone/login_form?came_from=http%3A//nohost'
)
def test_format_time(self):
python_time = datetime(2009, 02, 01, 23, 32, 03, 57)
@ -473,10 +738,8 @@ class TestCommentsViewlet(unittest.TestCase):
# time of the local time given above. That way, the time for the
# example below is correct within each time zone, independent of DST
python_time = datetime(
*time.gmtime(time.mktime(python_time.timetuple()))[:7])
*time.gmtime(time.mktime(python_time.timetuple()))[:7]
)
localized_time = self.viewlet.format_time(python_time)
self.assertEqual(localized_time, 'Feb 01, 2009 11:32 PM')
def test_suite():
return unittest.defaultTestLoader.loadTestsFromName(__name__)
self.assertTrue(
localized_time in ['Feb 01, 2009 11:32 PM', '2009-02-01 23:32'])

View File

@ -0,0 +1,135 @@
# -*- coding: utf-8 -*-
import unittest2 as unittest
from zope.component import createObject, getAdapter
from plone.app.testing import TEST_USER_ID, setRoles
from plone.contentrules.rule.interfaces import IRuleEventType
from plone.stringinterp.interfaces import IStringSubstitution
from plone.app.discussion.interfaces import IConversation, IReplies
from plone.app.discussion.interfaces import ICommentAddedEvent
from plone.app.discussion.interfaces import ICommentRemovedEvent
from plone.app.discussion.interfaces import IReplyAddedEvent
from plone.app.discussion.interfaces import IReplyRemovedEvent
from plone.app.discussion.testing import (
PLONE_APP_DISCUSSION_INTEGRATION_TESTING,
)
class CommentContentRulesTest(unittest.TestCase):
""" Test custom comments events
"""
layer = PLONE_APP_DISCUSSION_INTEGRATION_TESTING
def setUp(self):
# Setup sandbox
self.portal = self.layer['portal']
self.request = self.layer['request']
# Setup current user properties
member = self.portal.portal_membership.getMemberById(TEST_USER_ID)
member.setMemberProperties({
'fullname': 'X Manager',
'email': 'xmanager@example.com'
})
setRoles(self.portal, TEST_USER_ID, ['Manager'])
self.document = self.portal['doc1']
comment = createObject('plone.Comment')
comment.text = "This is a comment"
comment.author_username = "jim"
comment.author_name = "Jim"
comment.author_email = "jim@example.com"
conversation = IConversation(self.document)
conversation.addComment(comment)
def testEventTypesMarked(self):
self.assertTrue(IRuleEventType.providedBy(ICommentAddedEvent))
self.assertTrue(IRuleEventType.providedBy(ICommentRemovedEvent))
self.assertTrue(IRuleEventType.providedBy(IReplyAddedEvent))
self.assertTrue(IRuleEventType.providedBy(IReplyRemovedEvent))
def testCommentIdStringSubstitution(self):
comment_id = getAdapter(self.document, IStringSubstitution,
name=u"comment_id")
self.assertIsInstance(comment_id(), long)
def testCommentTextStringSubstitution(self):
comment_text = getAdapter(self.document, IStringSubstitution,
name=u"comment_text")
self.assertEqual(comment_text(), u"This is a comment")
def testCommentUserIdStringSubstitution(self):
comment_user_id = getAdapter(self.document, IStringSubstitution,
name=u"comment_user_id")
self.assertEqual(comment_user_id(), u"jim")
def testCommentUserFullNameStringSubstitution(self):
comment_user_fullname = getAdapter(self.document, IStringSubstitution,
name=u"comment_user_fullname")
self.assertEqual(comment_user_fullname(), u"Jim")
def testCommentUserEmailStringSubstitution(self):
comment_user_email = getAdapter(self.document, IStringSubstitution,
name=u"comment_user_email")
self.assertEqual(comment_user_email(), u"jim@example.com")
class ReplyContentRulesTest(unittest.TestCase):
""" Test custom comments events
"""
layer = PLONE_APP_DISCUSSION_INTEGRATION_TESTING
def setUp(self):
# Setup sandbox
self.portal = self.layer['portal']
self.request = self.layer['request']
setRoles(self.portal, TEST_USER_ID, ['Manager'])
self.document = self.portal['doc1']
conversation = IConversation(self.document)
replies = IReplies(conversation)
comment = createObject('plone.Comment')
comment.text = 'This is a comment'
new_id = replies.addComment(comment)
comment = self.document.restrictedTraverse(
'++conversation++default/%s' % new_id)
re_comment = createObject('plone.Comment')
re_comment.text = 'This is a reply'
re_comment.author_username = "julia"
re_comment.author_name = "Juliana"
re_comment.author_email = "julia@example.com"
replies = IReplies(comment)
new_re_id = replies.addComment(re_comment)
def testReplyIdStringSubstitution(self):
reply_id = getAdapter(self.document, IStringSubstitution,
name=u"comment_id")
self.assertIsInstance(reply_id(), long)
def testReplyTextStringSubstitution(self):
reply_text = getAdapter(self.document, IStringSubstitution,
name=u"comment_text")
self.assertEqual(reply_text(), u"This is a reply")
def testReplyUserIdStringSubstitution(self):
reply_user_id = getAdapter(self.document, IStringSubstitution,
name=u"comment_user_id")
self.assertEqual(reply_user_id(), u"julia")
def testReplyUserFullNameStringSubstitution(self):
reply_user_fullname = getAdapter(self.document, IStringSubstitution,
name=u"comment_user_fullname")
self.assertEqual(reply_user_fullname(), u"Juliana")
def testReplyUserEmailStringSubstitution(self):
reply_user_email = getAdapter(self.document, IStringSubstitution,
name=u"comment_user_email")
self.assertEqual(reply_user_email(), u"julia@example.com")

View File

@ -31,65 +31,116 @@ class RegistryTest(unittest.TestCase):
self.assertTrue(registry.forInterface(IDiscussionSettings))
def test_discussion_controlpanel_view(self):
view = getMultiAdapter((self.portal, self.portal.REQUEST),
name="discussion-settings")
view = getMultiAdapter(
(self.portal, self.portal.REQUEST),
name="discussion-controlpanel"
)
view = view.__of__(self.portal)
self.assertTrue(view())
def test_discussion_in_controlpanel(self):
# Check if discussion is in the control panel
self.controlpanel = getToolByName(self.portal, "portal_controlpanel")
self.assertTrue('discussion' in [a.getAction(self)['id']
for a in self.controlpanel.listActions()])
self.assertTrue(
'discussion' in [
a.getAction(self)['id']
for a in self.controlpanel.listActions()
]
)
def test_globally_enabled(self):
# Check globally_enabled record
self.assertTrue('globally_enabled' in IDiscussionSettings)
self.assertEqual(
self.registry['plone.app.discussion.interfaces.' +
'IDiscussionSettings.globally_enabled'],
False)
self.registry[
'plone.app.discussion.interfaces.' +
'IDiscussionSettings.globally_enabled'
],
False
)
def test_anonymous_comments(self):
# Check anonymous_comments record
self.assertTrue('anonymous_comments' in IDiscussionSettings)
self.assertEqual(self.registry['plone.app.discussion.interfaces.' +
'IDiscussionSettings.anonymous_comments'], False)
self.assertEqual(
self.registry[
'plone.app.discussion.interfaces.' +
'IDiscussionSettings.anonymous_comments'
],
False
)
def test_moderation_enabled(self):
# Check globally_enabled record
self.assertTrue('moderation_enabled' in IDiscussionSettings)
self.assertEqual(
self.registry[
'plone.app.discussion.interfaces.' +
'IDiscussionSettings.moderation_enabled'
],
False
)
def test_edit_comment_enabled(self):
# Check edit_comment_enabled record
self.assertTrue('edit_comment_enabled' in IDiscussionSettings)
self.assertEqual(
self.registry['plone.app.discussion.interfaces.' +
'IDiscussionSettings.moderation_enabled'],
'IDiscussionSettings.edit_comment_enabled'],
False)
def test_delete_own_comment_enabled(self):
# Check delete_own_comment_enabled record
self.assertTrue('delete_own_comment_enabled' in IDiscussionSettings)
self.assertEqual(
self.registry['plone.app.discussion.interfaces.' +
'IDiscussionSettings.delete_own_comment_enabled'],
False)
def test_text_transform(self):
self.assertTrue('text_transform' in IDiscussionSettings)
self.assertEqual(
self.registry['plone.app.discussion.interfaces.' +
'IDiscussionSettings.text_transform'],
'text/plain')
self.registry[
'plone.app.discussion.interfaces.' +
'IDiscussionSettings.text_transform'
],
'text/plain'
)
def test_captcha(self):
# Check globally_enabled record
self.assertTrue('captcha' in IDiscussionSettings)
self.assertEqual(self.registry['plone.app.discussion.interfaces.' +
'IDiscussionSettings.captcha'],
'disabled')
self.assertEqual(
self.registry[
'plone.app.discussion.interfaces.' +
'IDiscussionSettings.captcha'
],
'disabled'
)
def test_show_commenter_image(self):
# Check show_commenter_image record
self.assertTrue('show_commenter_image' in IDiscussionSettings)
self.assertEqual(self.registry['plone.app.discussion.interfaces.' +
'IDiscussionSettings.show_commenter_image'], True)
self.assertEqual(
self.registry[
'plone.app.discussion.interfaces.' +
'IDiscussionSettings.show_commenter_image'
],
True
)
def test_moderator_notification_enabled(self):
# Check show_commenter_image record
self.assertTrue('moderator_notification_enabled' in
IDiscussionSettings)
self.assertEqual(self.registry['plone.app.discussion.interfaces.' +
'IDiscussionSettings.moderator_notification_enabled'], False)
self.assertTrue(
'moderator_notification_enabled' in IDiscussionSettings
)
self.assertEqual(
self.registry[
'plone.app.discussion.interfaces.' +
'IDiscussionSettings.moderator_notification_enabled'
],
False
)
#def test_user_notification_enabled(self):
# # Check show_commenter_image record
@ -117,23 +168,32 @@ class ConfigurationChangedSubscriberTest(unittest.TestCase):
changes.
"""
# By default the one_state_workflow without moderation is enabled
self.assertEqual(('one_state_workflow',),
self.assertEqual(
('one_state_workflow',),
self.portal.portal_workflow.getChainForPortalType(
'Discussion Item'))
'Discussion Item'
)
)
# Enable moderation in the discussion control panel
self.settings.moderation_enabled = True
# Make sure the comment_review_workflow with moderation enabled is
# enabled
self.assertEqual(('comment_review_workflow',),
self.assertEqual(
('comment_review_workflow',),
self.portal.portal_workflow.getChainForPortalType(
'Discussion Item'))
'Discussion Item'
)
)
# And back
self.settings.moderation_enabled = False
self.assertEqual(('one_state_workflow',),
self.assertEqual(
('one_state_workflow',),
self.portal.portal_workflow.getChainForPortalType(
'Discussion Item'))
'Discussion Item'
)
)
def test_change_workflow_in_types_control_panel(self):
"""Make sure the setting in the discussion control panel is changed
@ -146,7 +206,8 @@ class ConfigurationChangedSubscriberTest(unittest.TestCase):
# Enable the 'comment_review_workflow' with moderation enabled
self.portal.portal_workflow.setChainForPortalTypes(
('Discussion Item',),
('comment_review_workflow',))
('comment_review_workflow',)
)
# Make sure the moderation_enabled settings has changed
self.settings.moderation_enabled = True
@ -154,19 +215,17 @@ class ConfigurationChangedSubscriberTest(unittest.TestCase):
# Enable the 'comment_review_workflow' with moderation enabled
self.portal.portal_workflow.setChainForPortalTypes(
('Discussion Item',),
('one_state_workflow',))
('one_state_workflow',)
)
self.settings.moderation_enabled = True
# Enable a 'custom' discussion workflow
self.portal.portal_workflow.setChainForPortalTypes(
('Discussion Item',),
('intranet_workflow',))
('intranet_workflow',)
)
# Setting has not changed. A Custom workflow disables the
# enable_moderation checkbox in the discussion control panel. The
# setting itself remains unchanged.
self.settings.moderation_enabled = True
def test_suite():
return unittest.defaultTestLoader.loadTestsFromName(__name__)

View File

@ -15,8 +15,9 @@ from Products.CMFCore.utils import getToolByName
from plone.app.testing import TEST_USER_ID, setRoles
from plone.app.discussion.testing import \
from plone.app.discussion.testing import (
PLONE_APP_DISCUSSION_INTEGRATION_TESTING
)
from plone.app.discussion import interfaces
from plone.app.discussion.interfaces import IConversation
@ -25,7 +26,7 @@ from plone.app.discussion.interfaces import IReplies
from plone.app.discussion.interfaces import IDiscussionSettings
try:
import plone.dexterity
from plone.dexterity.interfaces import IDexterityContent
DEXTERITY = True
except:
DEXTERITY = False
@ -41,12 +42,12 @@ class ConversationTest(unittest.TestCase):
interface.alsoProvides(
self.portal.REQUEST, interfaces.IDiscussionLayer)
typetool = self.portal.portal_types
typetool.constructContent('Document', self.portal, 'doc1')
self.typetool = typetool
self.portal_discussion = getToolByName(self.portal,
self.typetool = self.portal.portal_types
self.portal_discussion = getToolByName(
self.portal,
'portal_discussion',
None)
None,
)
# Allow discussion
registry = queryUtility(IRegistry)
settings = registry.forInterface(IDiscussionSettings)
@ -68,14 +69,30 @@ class ConversationTest(unittest.TestCase):
# Check that the conversation methods return the correct data
self.assertTrue(isinstance(comment.comment_id, long))
self.assertTrue(IComment.providedBy(conversation[new_id]))
self.assertEqual(aq_base(conversation[new_id].__parent__),
aq_base(conversation))
self.assertEqual(
aq_base(conversation[new_id].__parent__),
aq_base(conversation)
)
self.assertEqual(new_id, comment.comment_id)
self.assertEqual(len(list(conversation.getComments())), 1)
self.assertEqual(len(tuple(conversation.getThreads())), 1)
self.assertEqual(conversation.total_comments, 1)
self.assertTrue(conversation.last_comment_date - datetime.utcnow() <
timedelta(seconds=1))
self.assertEqual(conversation.total_comments(), 1)
self.assertTrue(
conversation.last_comment_date - datetime.utcnow() <
timedelta(seconds=1)
)
def test_private_comment(self):
conversation = IConversation(self.portal.doc1)
comment = createObject('plone.Comment')
comment.author_username = "nobody"
conversation.addComment(comment)
comment.manage_permission("View", roles=tuple())
self.assertEqual(0, conversation.total_comments())
self.assertEqual(None, conversation.last_comment_date)
self.assertEqual(["nobody"], list(conversation.commentators))
self.assertEqual([], list(conversation.public_commentators))
def test_delete_comment(self):
# Create a conversation. In this case we doesn't assign it to an
@ -93,7 +110,7 @@ class ConversationTest(unittest.TestCase):
# make sure the comment has been added
self.assertEqual(len(list(conversation.getComments())), 1)
self.assertEqual(len(tuple(conversation.getThreads())), 1)
self.assertEqual(conversation.total_comments, 1)
self.assertEqual(conversation.total_comments(), 1)
# delete the comment we just created
del conversation[new_id]
@ -101,7 +118,7 @@ class ConversationTest(unittest.TestCase):
# make sure there is no comment left in the conversation
self.assertEqual(len(list(conversation.getComments())), 0)
self.assertEqual(len(tuple(conversation.getThreads())), 0)
self.assertEqual(conversation.total_comments, 0)
self.assertEqual(conversation.total_comments(), 0)
def test_delete_recursive(self):
# Create a conversation. In this case we doesn't assign it to an
@ -157,8 +174,8 @@ class ConversationTest(unittest.TestCase):
del conversation[new_id_1]
self.assertEqual(
[{'comment': comment2, 'depth': 0, 'id': new_id_2},
self.assertEqual([
{'comment': comment2, 'depth': 0, 'id': new_id_2},
{'comment': comment2_1, 'depth': 1, 'id': new_id_2_1},
], list(conversation.getThreads()))
@ -176,72 +193,7 @@ class ConversationTest(unittest.TestCase):
# Make sure the comment has been deleted as well
self.assertEqual(len(list(conversation.getComments())), 0)
self.assertEqual(len(tuple(conversation.getThreads())), 0)
self.assertEqual(conversation.total_comments, 0)
def test_allow_discussion(self):
# This is not a real test! It's only there to understand the
# allow discussion attribute. Maybe we should remove this at
# some point.
# 1) allow_discussion attribute: Every content object in Plone
# has a allow_discussion attribute. By default it is set to None.
# Create a conversation.
IConversation(self.portal.doc1)
# By default, discussion is disabled for all content types
portal_types = getToolByName(self.portal, 'portal_types')
for type in list(portal_types):
type_fti = getattr(portal_types, type)
if type not in BAD_TYPES:
if type != 'Discussion Item':
self.assertFalse(type_fti.allowDiscussion())
# By default, allow_discussion on newly created content objects is
# set to False
portal_discussion = getToolByName(self.portal, 'portal_discussion')
self.assertEqual(portal_discussion.isDiscussionAllowedFor(
self.portal.doc1), False)
self.assertEqual(self.portal.doc1.getTypeInfo().allowDiscussion(),
False)
# The allow discussion flag is None by default
self.assertFalse(getattr(self.portal.doc1, 'allow_discussion', None))
# But isDiscussionAllowedFor, also checks if discussion is allowed on
# the content type. So we allow discussion on the Document content
# type and check if the Document object allows discussion now.
document_fti = getattr(portal_types, 'Document')
document_fti.manage_changeProperties(allow_discussion=True)
self.assertEqual(portal_discussion.isDiscussionAllowedFor(
self.portal.doc1), True)
self.assertEqual(self.portal.doc1.getTypeInfo().allowDiscussion(),
True)
# We can also override the allow_discussion locally
self.portal_discussion.overrideDiscussionFor(self.portal.doc1, False)
# Check if the Document discussion is disabled
self.assertEqual(portal_discussion.isDiscussionAllowedFor(
self.portal.doc1), False)
# Check that the local allow_discussion flag is now explicitly set to
# False
self.assertEqual(getattr(self.portal.doc1, 'allow_discussion', None),
False)
# Disallow discussion on the Document content type again
document_fti.manage_changeProperties(allow_discussion=False)
self.assertEqual(portal_discussion.isDiscussionAllowedFor(
self.portal.doc1), False)
self.assertEqual(self.portal.doc1.getTypeInfo().allowDiscussion(),
False)
# Now we override allow_discussion again (True) for the Document
# content object
self.portal_discussion.overrideDiscussionFor(self.portal.doc1, True)
self.assertEqual(portal_discussion.isDiscussionAllowedFor(
self.portal.doc1), True)
self.assertEqual(getattr(self.portal.doc1, 'allow_discussion', None),
True)
self.assertEqual(conversation.total_comments(), 0)
def test_comments_enabled_on_doc_in_subfolder(self):
typetool = self.portal.portal_types
@ -249,11 +201,10 @@ class ConversationTest(unittest.TestCase):
typetool.constructContent('Document', self.portal.folder1, 'doc2')
folder = self.portal.folder1
folder.allowDiscussion(False)
self.assertFalse(hasattr(aq_base(folder), 'allow_discussion'))
folder.allowDiscussion(True)
folder.allow_discussion = True
self.assertTrue(aq_base(folder).allow_discussion)
folder.allowDiscussion(False)
folder.allow_discussion = False
self.assertFalse(aq_base(folder).allow_discussion)
doc = self.portal.folder1.doc2
@ -326,7 +277,8 @@ class ConversationTest(unittest.TestCase):
# Create a conversation.
conversation = self.portal.doc1.restrictedTraverse(
'@@conversation_view')
'@@conversation_view'
)
# The Document content type is disabled by default
self.assertEqual(conversation.enabled(), False)
@ -348,74 +300,44 @@ class ConversationTest(unittest.TestCase):
self.assertEqual(conversation.enabled(), False)
def test_allow_discussion_on_folder(self):
# The enabled method should always return False for the folder
# itself.
# The ATContentTypes based allow_discussion method did not allow to
# allow discussion on a folder. The dexerity behavior shipped with
# plone.app.contenttypes does not have this restriction any longer.
# Create a folderp
# Create a folder
self.typetool.constructContent('Folder', self.portal, 'f1')
f1 = self.portal.f1
# Usually we don't create a conversation on a folder
conversation = self.portal.f1.restrictedTraverse('@@conversation_view')
# Allow discussion for the folder
self.portal_discussion.overrideDiscussionFor(f1, True)
self.portal.f1.allow_discussion = True
# Allow discussion on Folder content type
portal_types = getToolByName(self.portal, 'portal_types')
document_fti = getattr(portal_types, 'Folder')
document_fti.manage_changeProperties(allow_discussion=True)
# Always return False
self.assertFalse(conversation.enabled())
def test_is_discussion_allowed_for_folder(self):
# When a content item provides IFolderish from CMF and
# does not provide INonStructuralFolder from Plone,
# allow_discussion acts as an on/off flag for all items
# in that folder, overriding settings for any parent folders,
# and the for the FTI, but is overridden by child items and
# folders further down.
# Create a folder
self.typetool.constructContent('Folder', self.portal, 'f1')
f1 = self.portal.f1
# Create a document inside the folder
self.typetool.constructContent('Document', f1, 'doc1')
doc1 = self.portal.f1.doc1
doc1_conversation = doc1.restrictedTraverse('@@conversation_view')
self.assertEqual(doc1_conversation.enabled(), False)
# Allow commenting for the folder
self.portal_discussion.overrideDiscussionFor(f1, True)
# Check if the content objects allows discussion
self.assertEqual(doc1_conversation.enabled(), True)
# Turn commenting for the folder off
self.portal_discussion.overrideDiscussionFor(f1, False)
# Check if content objects do not allow discussion anymore
self.assertEqual(doc1_conversation.enabled(), False)
self.assertTrue(conversation.enabled())
def test_is_discussion_allowed_on_content_object(self):
# Allow discussion on a single content object
# Create a conversation.
conversation = self.portal.doc1.restrictedTraverse(
'@@conversation_view')
'@@conversation_view'
)
# Discussion is disallowed by default
self.assertEqual(conversation.enabled(), False)
# Allow discussion on content object
self.portal_discussion.overrideDiscussionFor(self.portal.doc1, True)
self.portal.doc1.allow_discussion = True
# Check if discussion is now allowed on the content object
self.assertEqual(conversation.enabled(), True)
self.portal_discussion.overrideDiscussionFor(self.portal.doc1, False)
self.portal.doc1.allow_discussion = False
self.assertEqual(conversation.enabled(), False)
def test_dict_operations(self):
@ -498,7 +420,7 @@ class ConversationTest(unittest.TestCase):
conversation.addComment(comment2)
conversation.addComment(comment3)
self.assertEqual(conversation.total_comments, 3)
self.assertEqual(conversation.total_comments(), 3)
def test_commentators(self):
# add and remove a few comments to make sure the commentators
@ -508,7 +430,7 @@ class ConversationTest(unittest.TestCase):
# object, as we just want to check the Conversation object API.
conversation = IConversation(self.portal.doc1)
self.assertEqual(conversation.total_comments, 0)
self.assertEqual(conversation.total_comments(), 0)
# Add a four comments from three different users
# Note: in real life, we always create
@ -535,7 +457,7 @@ class ConversationTest(unittest.TestCase):
new_comment4_id = conversation.addComment(comment4)
# check if all commentators are in the commentators list
self.assertEqual(conversation.total_comments, 4)
self.assertEqual(conversation.total_comments(), 4)
self.assertTrue('Jim' in conversation.commentators)
self.assertTrue('Joe' in conversation.commentators)
self.assertTrue('Jack' in conversation.commentators)
@ -548,7 +470,7 @@ class ConversationTest(unittest.TestCase):
self.assertTrue('Jim' in conversation.commentators)
self.assertTrue('Joe' in conversation.commentators)
self.assertTrue('Jack' in conversation.commentators)
self.assertEqual(conversation.total_comments, 3)
self.assertEqual(conversation.total_comments(), 3)
# remove the second comment from Jack
del conversation[new_comment4_id]
@ -557,7 +479,7 @@ class ConversationTest(unittest.TestCase):
self.assertTrue('Jim' in conversation.commentators)
self.assertTrue('Joe' in conversation.commentators)
self.assertFalse('Jack' in conversation.commentators)
self.assertEqual(conversation.total_comments, 2)
self.assertEqual(conversation.total_comments(), 2)
def test_last_comment_date(self):
# add and remove some comments and check if last_comment_date
@ -587,30 +509,42 @@ class ConversationTest(unittest.TestCase):
new_comment3_id = conversation.addComment(comment3)
# check if the latest comment is exactly one day old
self.assertTrue(conversation.last_comment_date < datetime.utcnow() -
timedelta(hours=23, minutes=59, seconds=59))
self.assertTrue(conversation.last_comment_date >
datetime.utcnow() - timedelta(days=1, seconds=1))
self.assertTrue(
conversation.last_comment_date < datetime.utcnow() -
timedelta(hours=23, minutes=59, seconds=59)
)
self.assertTrue(
conversation.last_comment_date >
datetime.utcnow() - timedelta(days=1, seconds=1)
)
# remove the latest comment
del conversation[new_comment3_id]
# check if the latest comment has been updated
# the latest comment should be exactly two days old
self.assertTrue(conversation.last_comment_date < datetime.utcnow() -
timedelta(days=1, hours=23, minutes=59, seconds=59))
self.assertTrue(conversation.last_comment_date > datetime.utcnow() -
timedelta(days=2, seconds=1))
self.assertTrue(
conversation.last_comment_date < datetime.utcnow() -
timedelta(days=1, hours=23, minutes=59, seconds=59)
)
self.assertTrue(
conversation.last_comment_date > datetime.utcnow() -
timedelta(days=2, seconds=1)
)
# remove the latest comment again
del conversation[new_comment2_id]
# check if the latest comment has been updated
# the latest comment should be exactly four days old
self.assertTrue(conversation.last_comment_date < datetime.utcnow() -
timedelta(days=3, hours=23, minutes=59, seconds=59))
self.assertTrue(conversation.last_comment_date > datetime.utcnow() -
timedelta(days=4, seconds=2))
self.assertTrue(
conversation.last_comment_date < datetime.utcnow() -
timedelta(days=3, hours=23, minutes=59, seconds=59)
)
self.assertTrue(
conversation.last_comment_date > datetime.utcnow() -
timedelta(days=4, seconds=2)
)
def test_get_comments_full(self):
pass
@ -673,8 +607,8 @@ class ConversationTest(unittest.TestCase):
# Get threads
self.assertEqual(
[{'comment': comment1, 'depth': 0, 'id': new_id_1},
self.assertEqual([
{'comment': comment1, 'depth': 0, 'id': new_id_1},
{'comment': comment1_1, 'depth': 1, 'id': new_id_1_1},
{'comment': comment1_1_1, 'depth': 2, 'id': new_id_1_1_1},
{'comment': comment1_2, 'depth': 1, 'id': new_id_1_2},
@ -691,13 +625,27 @@ class ConversationTest(unittest.TestCase):
# make sure we can traverse to conversations and get a URL and path
conversation = self.portal.doc1.restrictedTraverse(
'++conversation++default')
'++conversation++default'
)
self.assertTrue(IConversation.providedBy(conversation))
self.assertEqual(('', 'plone', 'doc1', '++conversation++default'),
conversation.getPhysicalPath())
self.assertEqual('http://nohost/plone/doc1/++conversation++default',
conversation.absolute_url())
self.assertEqual(
('', 'plone', 'doc1', '++conversation++default'),
conversation.getPhysicalPath()
)
self.assertEqual(
'http://nohost/plone/doc1/++conversation++default',
conversation.absolute_url()
)
def test_unconvertible_id(self):
# make sure the conversation view doesn't break when given comment id
# can't be converted to long
conversation = self.portal.doc1.restrictedTraverse(
'++conversation++default/ThisCantBeRight'
)
self.assertEqual(conversation, None)
def test_parent(self):
# Check that conversation has a content object as parent
@ -717,8 +665,10 @@ class ConversationTest(unittest.TestCase):
def test_no_comment(self):
IConversation(self.portal.doc1)
# Make sure no conversation has been created
self.assertTrue('plone.app.discussion:conversation' not in
IAnnotations(self.portal.doc1))
self.assertTrue(
'plone.app.discussion:conversation' not in
IAnnotations(self.portal.doc1)
)
class ConversationEnabledForDexterityTypesTest(unittest.TestCase):
@ -730,15 +680,14 @@ class ConversationEnabledForDexterityTypesTest(unittest.TestCase):
setRoles(self.portal, TEST_USER_ID, ['Manager'])
interface.alsoProvides(
self.portal.REQUEST,
interfaces.IDiscussionLayer)
interfaces.IDiscussionLayer
)
typetool = self.portal.portal_types
typetool.constructContent('Document', self.portal, 'doc1')
if DEXTERITY:
from plone.dexterity.interfaces import IDexterityContent
interface.alsoProvides(
self.portal.doc1,
IDexterityContent)
IDexterityContent
)
def _makeOne(self, *args, **kw):
return self.portal.doc1.restrictedTraverse('@@conversation_view')
@ -797,8 +746,6 @@ class RepliesTest(unittest.TestCase):
def setUp(self):
self.portal = self.layer['portal']
setRoles(self.portal, TEST_USER_ID, ['Manager'])
typetool = self.portal.portal_types
typetool.constructContent('Document', self.portal, 'doc1')
def test_add_comment(self):
# Add comments to a ConversationReplies adapter
@ -915,12 +862,8 @@ class RepliesTest(unittest.TestCase):
# check that replies only contain the direct comments
# and no comments deeper than 1
self.assertEqual(conversation.total_comments, 6)
self.assertEqual(conversation.total_comments(), 6)
self.assertEqual(len(replies), 2)
self.assertEqual(len(replies_to_comment1), 2)
self.assertEqual(len(replies_to_comment1_1), 1)
self.assertEqual(len(replies_to_comment2), 1)
def test_suite():
return unittest.defaultTestLoader.loadTestsFromName(__name__)

View File

@ -0,0 +1,169 @@
# -*- coding: utf-8 -*-
import unittest2 as unittest
from zope.component import createObject
from Zope2.App import zcml
import Products.Five
from plone.app.testing import TEST_USER_ID, setRoles
from plone.app.discussion.interfaces import IConversation, IReplies
from plone.app.discussion.testing import (
PLONE_APP_DISCUSSION_INTEGRATION_TESTING,
)
#
# Fake events registry
#
class EventsRegistry(object):
""" Fake registry to be used while testing discussion events
"""
commentAdded = False
commentRemoved = False
replyAdded = False
replyRemoved = False
#
# Fake event handlers
#
def comment_added(doc, evt):
EventsRegistry.commentAdded = True
def comment_removed(doc, evt):
EventsRegistry.commentRemoved = True
def reply_added(doc, evt):
EventsRegistry.replyAdded = True
def reply_removed(doc, evt):
EventsRegistry.replyRemoved = True
#
# Tests
#
class CommentEventsTest(unittest.TestCase):
""" Test custom comments events
"""
layer = PLONE_APP_DISCUSSION_INTEGRATION_TESTING
def setUp(self):
# Setup sandbox
self.portal = self.layer['portal']
self.request = self.layer['request']
self.registry = EventsRegistry
setRoles(self.portal, TEST_USER_ID, ['Manager'])
self.document = self.portal['doc1']
#
# Subscribers
#
configure = """
<configure
xmlns="http://namespaces.zope.org/zope">
<subscriber
for="OFS.interfaces.ISimpleItem
plone.app.discussion.interfaces.ICommentAddedEvent"
handler="plone.app.discussion.tests.test_events.comment_added"
/>
<subscriber
for="OFS.interfaces.ISimpleItem
plone.app.discussion.interfaces.ICommentRemovedEvent"
handler="plone.app.discussion.tests.test_events.comment_removed"
/>
</configure>
"""
zcml.load_config("configure.zcml", Products.Five)
zcml.load_string(configure)
def test_addEvent(self):
self.assertFalse(self.registry.commentAdded)
comment = createObject('plone.Comment')
conversation = IConversation(self.document)
conversation.addComment(comment)
self.assertTrue(self.registry.commentAdded)
def test_removedEvent(self):
self.assertFalse(self.registry.commentRemoved)
comment = createObject('plone.Comment')
conversation = IConversation(self.document)
cid = conversation.addComment(comment)
del conversation[cid]
self.assertTrue(self.registry.commentRemoved)
class RepliesEventsTest(unittest.TestCase):
""" Test custom replies events
"""
layer = PLONE_APP_DISCUSSION_INTEGRATION_TESTING
def setUp(self):
self.portal = self.layer['portal']
self.request = self.layer['request']
self.registry = EventsRegistry
setRoles(self.portal, TEST_USER_ID, ['Manager'])
self.document = self.portal['doc1']
#
# Subscribers
#
configure = """
<configure
xmlns="http://namespaces.zope.org/zope">
<subscriber
for="OFS.interfaces.ISimpleItem
plone.app.discussion.interfaces.IReplyAddedEvent"
handler="plone.app.discussion.tests.test_events.reply_added"
/>
<subscriber
for="OFS.interfaces.ISimpleItem
plone.app.discussion.interfaces.IReplyRemovedEvent"
handler="plone.app.discussion.tests.test_events.reply_removed"
/>
</configure>
"""
zcml.load_config("configure.zcml", Products.Five)
zcml.load_string(configure)
def test_addEvent(self):
self.assertFalse(self.registry.replyAdded)
conversation = IConversation(self.document)
replies = IReplies(conversation)
comment = createObject('plone.Comment')
comment.text = 'Comment text'
new_id = replies.addComment(comment)
comment = self.document.restrictedTraverse(
'++conversation++default/%s' % new_id)
re_comment = createObject('plone.Comment')
re_comment.text = 'Comment text'
replies = IReplies(comment)
new_re_id = replies.addComment(re_comment)
self.assertTrue(self.registry.replyAdded)
def test_removedEvent(self):
self.assertFalse(self.registry.replyRemoved)
conversation = IConversation(self.portal.doc1)
replies = IReplies(conversation)
comment = createObject('plone.Comment')
comment.text = 'Comment text'
new_id = replies.addComment(comment)
comment = self.portal.doc1.restrictedTraverse(
'++conversation++default/%s' % new_id)
re_comment = createObject('plone.Comment')
re_comment.text = 'Comment text'
replies = IReplies(comment)
new_re_id = replies.addComment(re_comment)
del replies[new_re_id]
self.assertTrue(self.registry.replyRemoved)

View File

@ -15,12 +15,13 @@ from plone.app.discussion.testing import \
optionflags = (
doctest.ELLIPSIS | \
doctest.NORMALIZE_WHITESPACE | \
doctest.REPORT_ONLY_FIRST_FAILURE)
doctest.ELLIPSIS |
doctest.NORMALIZE_WHITESPACE |
doctest.REPORT_ONLY_FIRST_FAILURE
)
normal_testfiles = [
'functional_test_comments.txt',
'functional_test_comment_review_workflow.txt'
'functional_test_comment_review_workflow.txt',
]

View File

@ -40,10 +40,6 @@ class ConversationIndexersTest(unittest.TestCase):
self.portal = self.layer['portal']
setRoles(self.portal, TEST_USER_ID, ['Manager'])
self.portal.invokeFactory(id='doc1',
title='Document 1',
type_name='Document')
# Create a conversation.
conversation = IConversation(self.portal.doc1)
@ -74,8 +70,10 @@ class ConversationIndexersTest(unittest.TestCase):
self.conversation = conversation
def test_conversation_total_comments(self):
self.assertTrue(isinstance(catalog.total_comments,
DelegatingIndexerFactory))
self.assertTrue(isinstance(
catalog.total_comments,
DelegatingIndexerFactory
))
self.assertEqual(catalog.total_comments(self.portal.doc1)(), 3)
del self.conversation[self.new_id1]
self.assertEqual(catalog.total_comments(self.portal.doc1)(), 2)
@ -84,13 +82,19 @@ class ConversationIndexersTest(unittest.TestCase):
self.assertEqual(catalog.total_comments(self.portal.doc1)(), 0)
def test_conversation_last_comment_date(self):
self.assertTrue(isinstance(catalog.last_comment_date,
DelegatingIndexerFactory))
self.assertEqual(catalog.last_comment_date(self.portal.doc1)(),
datetime(2009, 4, 12, 11, 12, 12))
self.assertTrue(isinstance(
catalog.last_comment_date,
DelegatingIndexerFactory
))
self.assertEqual(
catalog.last_comment_date(self.portal.doc1)(),
datetime(2009, 4, 12, 11, 12, 12)
)
del self.conversation[self.new_id3]
self.assertEqual(catalog.last_comment_date(self.portal.doc1)(),
datetime(2007, 12, 13, 4, 18, 12))
self.assertEqual(
catalog.last_comment_date(self.portal.doc1)(),
datetime(2007, 12, 13, 4, 18, 12)
)
del self.conversation[self.new_id2]
del self.conversation[self.new_id1]
self.assertEqual(catalog.last_comment_date(self.portal.doc1)(), None)
@ -111,10 +115,6 @@ class CommentIndexersTest(unittest.TestCase):
self.portal = self.layer['portal']
setRoles(self.portal, TEST_USER_ID, ['Manager'])
self.portal.invokeFactory(id='doc1',
title='Document 1',
type_name='Document')
# Create a conversation. In this case we doesn't assign it to an
# object, as we just want to check the Conversation object API.
conversation = IConversation(self.portal.doc1)
@ -138,8 +138,10 @@ class CommentIndexersTest(unittest.TestCase):
self.assertTrue(isinstance(catalog.title, DelegatingIndexerFactory))
def test_description(self):
self.assertEqual(catalog.description(self.comment)(),
'Lorem ipsum dolor sit amet.')
self.assertEqual(
catalog.description(self.comment)(),
'Lorem ipsum dolor sit amet.'
)
self.assertTrue(
isinstance(catalog.description, DelegatingIndexerFactory))
@ -151,24 +153,36 @@ class CommentIndexersTest(unittest.TestCase):
comment_long.text = LONG_TEXT
self.conversation.addComment(comment_long)
self.assertEqual(catalog.description(comment_long)(),
LONG_TEXT_CUT.replace("\n", " "))
self.assertEqual(
catalog.description(comment_long)(),
LONG_TEXT_CUT.replace("\n", " ")
)
def test_dates(self):
# Test if created, modified, effective etc. are set correctly
self.assertEqual(catalog.created(self.comment)(),
DateTime(2006, 9, 17, 14, 18, 12, 'GMT'))
self.assertEqual(catalog.effective(self.comment)(),
DateTime(2006, 9, 17, 14, 18, 12, 'GMT'))
self.assertEqual(catalog.modified(self.comment)(),
DateTime(2008, 3, 12, 7, 32, 52, 'GMT'))
self.assertEqual(
catalog.created(self.comment)(),
DateTime(2006, 9, 17, 14, 18, 12, 'GMT')
)
self.assertEqual(
catalog.effective(self.comment)(),
DateTime(2006, 9, 17, 14, 18, 12, 'GMT')
)
self.assertEqual(
catalog.modified(self.comment)(),
DateTime(2008, 3, 12, 7, 32, 52, 'GMT')
)
def test_searchable_text(self):
# Test if searchable text is a concatenation of title and comment text
self.assertEqual(catalog.searchable_text(self.comment)(),
('Lorem ipsum dolor sit amet.'))
self.assertTrue(isinstance(catalog.searchable_text,
DelegatingIndexerFactory))
self.assertEqual(
catalog.searchable_text(self.comment)(),
('Lorem ipsum dolor sit amet.')
)
self.assertTrue(isinstance(
catalog.searchable_text,
DelegatingIndexerFactory
))
def test_creator(self):
self.assertEqual(catalog.creator(self.comment)(), ('jim'))
@ -177,7 +191,3 @@ class CommentIndexersTest(unittest.TestCase):
# make sure in_response_to returns the title or id of the content
# object the comment was added to
self.assertEqual(catalog.in_response_to(self.comment)(), 'Document 1')
def test_suite():
return unittest.defaultTestLoader.loadTestsFromName(__name__)

View File

@ -1,247 +0,0 @@
from datetime import datetime
from DateTime import DateTime
import unittest2 as unittest
from zope.annotation.interfaces import IAnnotations
from Products.CMFCore.utils import getToolByName
from plone.app.testing import TEST_USER_ID, setRoles
from plone.app.discussion.testing import \
PLONE_APP_DISCUSSION_INTEGRATION_TESTING
from plone.app.discussion.browser.migration import View
from plone.app.discussion.interfaces import IConversation, IComment
class MigrationTest(unittest.TestCase):
layer = PLONE_APP_DISCUSSION_INTEGRATION_TESTING
def _publish(self, reply):
# publish the reply
status = self.portal.portal_workflow.getStatusOf(
'comment_review_workflow', reply).copy()
status['review_state'] = 'published'
self.portal.portal_workflow.setStatusOf(
'comment_review_workflow', reply, status)
def setUp(self):
self.portal = self.layer['portal']
self.request = self.layer['request']
setRoles(self.portal, TEST_USER_ID, ['Manager'])
self.portal.invokeFactory(id='doc',
title='Document 1',
type_name='Document')
# Create a document
self.discussion = getToolByName(self.portal, 'portal_discussion', None)
self.discussion.overrideDiscussionFor(self.portal.doc, 1)
# Publish it
self.workflowTool = getToolByName(self.portal, 'portal_workflow')
self.workflowTool.setDefaultChain('simple_publication_workflow')
self.workflowTool.doActionFor(self.portal.doc, 'publish')
self.request.set("test", True)
self.view = View(self.portal, self.request)
self.workflowTool.setChainForPortalTypes(('Discussion Item',),
'comment_review_workflow')
self.doc = self.portal.doc
def test_migrate_comment(self):
# Create a comment
talkback = self.discussion.getDiscussionFor(self.doc)
self.doc.talkback.createReply('My Title', 'My Text', Creator='Jim')
reply = talkback.getReplies()[0]
reply.setReplyTo(self.doc)
reply.creation_date = DateTime(2003, 3, 11, 9, 28, 6, 'GMT')
reply.modification_date = DateTime(2009, 7, 12, 19, 38, 7, 'GMT')
self._publish(reply)
self.assertEqual(reply.Title(), 'My Title')
self.assertEqual(reply.EditableBody(), 'My Text')
self.assertTrue('Jim' in reply.listCreators())
self.assertEqual(talkback.replyCount(self.doc), 1)
self.assertEqual(reply.inReplyTo(), self.doc)
# Call migration script
self.view()
# Make sure a conversation has been created
self.assertTrue('plone.app.discussion:conversation' in
IAnnotations(self.doc))
conversation = IConversation(self.doc)
# Check migration
self.assertEqual(conversation.total_comments, 1)
self.assertTrue(conversation.getComments().next())
comment1 = conversation.values()[0]
self.assertTrue(IComment.providedBy(comment1))
self.assertEqual(comment1.Title(), 'My Title')
self.assertEqual(comment1.text, '<p>My Text</p>\n')
self.assertEqual(comment1.mime_type, 'text/html')
self.assertEqual(comment1.Creator(), 'Jim')
self.assertEqual(comment1.creation_date,
datetime(2003, 3, 11, 9, 28, 6))
self.assertEqual(comment1.modification_date,
datetime(2009, 7, 12, 19, 38, 7))
self.assertEqual([
{'comment': comment1, 'depth': 0, 'id': long(comment1.id)}
], list(conversation.getThreads()))
self.assertFalse(self.doc.talkback)
def test_migrate_nested_comments(self):
# Create some nested comments and migrate them
#
# self.doc
# +- First comment
# +- Re: First comment
# + Re: Re: First comment
# + Re: Re: Re: First comment
# +- Re: First comment (2)
# +- Re: First comment (3)
# +- Re: First comment (4)
# +- Second comment
talkback = self.discussion.getDiscussionFor(self.doc)
# First comment
talkback.createReply(title='First comment',
text='This is my first comment.')
comment1 = talkback.getReplies()[0]
self._publish(comment1)
talkback_comment1 = self.discussion.getDiscussionFor(comment1)
# Re: First comment
talkback_comment1.createReply(title='Re: First comment',
text='This is my first reply.')
comment1_1 = talkback_comment1.getReplies()[0]
self._publish(comment1_1)
talkback_comment1_1 = self.discussion.getDiscussionFor(comment1_1)
self.assertEqual(len(talkback.getReplies()), 1)
self.assertEqual(len(talkback_comment1.getReplies()), 1)
self.assertEqual(len(talkback_comment1_1.getReplies()), 0)
#Re: Re: First comment
talkback_comment1_1.createReply(title='Re: Re: First comment',
text='This is my first re-reply.')
comment1_1_1 = talkback_comment1_1.getReplies()[0]
self._publish(comment1_1_1)
talkback_comment1_1_1 = self.discussion.getDiscussionFor(comment1_1_1)
# Re: Re: Re: First comment
talkback_comment1_1_1.createReply(title='Re: Re: Re: First comment',
text='This is my first re-re-reply.')
self._publish(talkback_comment1_1_1.getReplies()[0])
# Re: First comment (2)
talkback_comment1.createReply(title='Re: First comment (2)',
text='This is my first reply (2).')
self._publish(talkback_comment1.getReplies()[1])
# Re: First comment (3)
talkback_comment1.createReply(title='Re: First comment (3)',
text='This is my first reply (3).')
self._publish(talkback_comment1.getReplies()[2])
# Re: First comment (4)
talkback_comment1.createReply(title='Re: First comment (4)',
text='This is my first reply (4).')
self._publish(talkback_comment1.getReplies()[3])
# Second comment
talkback.createReply(title='Second comment',
text='This is my second comment.')
self._publish(talkback.getReplies()[1])
# Call migration script
self.view()
# Check migration
conversation = IConversation(self.doc)
self.assertEqual(conversation.total_comments, 8)
comment1 = conversation.values()[0]
comment1_1 = conversation.values()[1]
comment1_1_1 = conversation.values()[2]
comment1_1_1_1 = conversation.values()[3]
comment1_2 = conversation.values()[4]
comment1_3 = conversation.values()[5]
comment1_4 = conversation.values()[6]
comment2 = conversation.values()[7]
self.assertEqual(
[{'comment': comment1, 'depth': 0, 'id': long(comment1.id)},
{'comment': comment1_1, 'depth': 1, 'id': long(comment1_1.id)},
{'comment': comment1_1_1, 'depth': 2, 'id': long(comment1_1_1.id)},
{'comment': comment1_1_1_1, 'depth': 3,
'id': long(comment1_1_1_1.id)},
{'comment': comment1_2, 'depth': 1, 'id': long(comment1_2.id)},
{'comment': comment1_3, 'depth': 1, 'id': long(comment1_3.id)},
{'comment': comment1_4, 'depth': 1, 'id': long(comment1_4.id)},
{'comment': comment2, 'depth': 0, 'id': long(comment2.id)},
], list(conversation.getThreads()))
talkback = self.discussion.getDiscussionFor(self.doc)
self.assertEqual(len(talkback.getReplies()), 0)
def test_migrate_nested_comments_with_filter(self):
# Create some nested comments and migrate them.
# But use a filter that filters the top-level comment.
# All the comments should be removed, but not migrated.
#
# self.doc
# +- First comment
# +- Re: First comment
talkback = self.discussion.getDiscussionFor(self.doc)
# First comment
talkback.createReply(title='First comment',
text='This is my first comment.')
comment1 = talkback.getReplies()[0]
talkback_comment1 = self.discussion.getDiscussionFor(comment1)
# Re: First comment
talkback_comment1.createReply(title='Re: First comment',
text='This is my first reply.')
comment1_1 = talkback_comment1.getReplies()[0]
talkback_comment1_1 = self.discussion.getDiscussionFor(comment1_1)
self.assertEqual(len(talkback.getReplies()), 1)
self.assertEqual(len(talkback_comment1.getReplies()), 1)
self.assertEqual(len(talkback_comment1_1.getReplies()), 0)
def deny_comments(reply):
return False
# Call migration script
self.view(filter_callback=deny_comments)
# Check migration
conversation = IConversation(self.doc)
self.assertEqual(conversation.total_comments, 0)
talkback = self.discussion.getDiscussionFor(self.doc)
self.assertEqual(len(talkback.getReplies()), 0)
def test_migrate_no_comment(self):
# Call migration script
self.view()
# Make sure no conversation has been created
self.assertTrue('plone.app.discussion:conversation' not in
IAnnotations(self.doc))
def test_suite():
return unittest.defaultTestLoader.loadTestsFromName(__name__)

View File

@ -1,8 +1,6 @@
# -*- coding: utf-8 -*-
import unittest
from DateTime import DateTime
from zope.component import createObject
from Products.CMFCore.utils import getToolByName
@ -26,8 +24,6 @@ class ModerationViewTest(unittest.TestCase):
self.portal = self.layer['portal']
self.request = self.layer['request']
setRoles(self.portal, TEST_USER_ID, ['Manager'])
typetool = self.portal.portal_types
typetool.constructContent('Document', self.portal, 'doc1')
self.portal_discussion = getToolByName(self.portal,
'portal_discussion',
None)
@ -58,29 +54,6 @@ class ModerationViewTest(unittest.TestCase):
('comment_review_workflow,'))
self.assertEqual(self.view.moderation_enabled(), True)
def test_old_comments_not_shown_in_moderation_view(self):
# Create old comment
discussion = getToolByName(self.portal, 'portal_discussion', None)
discussion.overrideDiscussionFor(self.portal.doc1, 1)
talkback = discussion.getDiscussionFor(self.portal.doc1)
self.portal.doc1.talkback.createReply('My Title',
'My Text',
Creator='Jim')
reply = talkback.getReplies()[0]
reply.setReplyTo(self.portal.doc1)
reply.creation_date = DateTime(2003, 3, 11, 9, 28, 6)
reply.modification_date = DateTime(2009, 7, 12, 19, 38, 7)
self.assertEqual(reply.Title(), 'My Title')
self.assertEqual(reply.EditableBody(), 'My Text')
self.assertTrue('Jim' in reply.listCreators())
self.assertEqual(talkback.replyCount(self.portal.doc1), 1)
self.assertEqual(reply.inReplyTo(), self.portal.doc1)
view = self.view()
self.assertTrue('No comments to moderate' in view)
self.assertEqual(len(self.view.comments), 0)
class ModerationBulkActionsViewTest(unittest.TestCase):
@ -91,8 +64,6 @@ class ModerationBulkActionsViewTest(unittest.TestCase):
self.portal = self.layer['portal']
self.request = self.layer['request']
setRoles(self.portal, TEST_USER_ID, ['Manager'])
typetool = self.portal.portal_types
typetool.constructContent('Document', self.portal, 'doc1')
self.wf = getToolByName(self.portal,
'portal_workflow',
None)
@ -107,22 +78,25 @@ class ModerationBulkActionsViewTest(unittest.TestCase):
comment1.text = 'Comment text'
comment1.Creator = 'Jim'
new_id_1 = conversation.addComment(comment1)
self.comment1 = self.portal.doc1.restrictedTraverse(\
'++conversation++default/%s' % new_id_1)
self.comment1 = self.portal.doc1.restrictedTraverse(
'++conversation++default/%s' % new_id_1
)
comment2 = createObject('plone.Comment')
comment2.title = 'Comment 2'
comment2.text = 'Comment text'
comment2.Creator = 'Joe'
new_id_2 = conversation.addComment(comment2)
self.comment2 = self.portal.doc1.restrictedTraverse(\
'++conversation++default/%s' % new_id_2)
self.comment2 = self.portal.doc1.restrictedTraverse(
'++conversation++default/%s' % new_id_2
)
comment3 = createObject('plone.Comment')
comment3.title = 'Comment 3'
comment3.text = 'Comment text'
comment3.Creator = 'Emma'
new_id_3 = conversation.addComment(comment3)
self.comment3 = self.portal.doc1.restrictedTraverse(\
'++conversation++default/%s' % new_id_3)
self.comment3 = self.portal.doc1.restrictedTraverse(
'++conversation++default/%s' % new_id_3
)
self.conversation = conversation
def test_default_bulkaction(self):
@ -185,7 +159,3 @@ class ModerationBulkActionsViewTest(unittest.TestCase):
comment = self.conversation.getComments().next()
self.assertTrue(comment)
self.assertEqual(comment, self.comment2)
def test_suite():
return unittest.defaultTestLoader.loadTestsFromName(__name__)

View File

@ -7,11 +7,13 @@ from Acquisition import aq_base
from zope.component import createObject
from zope.component import getSiteManager
from zope.component import queryUtility
from zope.component import getUtility
from plone.app.testing import TEST_USER_ID, setRoles
from Products.MailHost.interfaces import IMailHost
from Products.CMFPlone.tests.utils import MockMailHost
from Products.CMFPlone.interfaces import IMailSchema
from plone.registry.interfaces import IRegistry
@ -34,15 +36,14 @@ class TestUserNotificationUnit(unittest.TestCase):
sm.unregisterUtility(provided=IMailHost)
sm.registerUtility(mailhost, provided=IMailHost)
# We need to fake a valid mail setup
self.portal.email_from_address = "portal@plone.test"
registry = getUtility(IRegistry)
mail_settings = registry.forInterface(IMailSchema, prefix='plone')
mail_settings.email_from_address = "portal@plone.test"
self.mailhost = self.portal.MailHost
# Enable user notification setting
registry = queryUtility(IRegistry)
registry['plone.app.discussion.interfaces.IDiscussionSettings' +
'.user_notification_enabled'] = True
# Create test content
self.portal.invokeFactory('Document', 'doc1')
self.portal_discussion = self.portal.portal_discussion
# Archetypes content types store data as utf-8 encoded strings
# The missing u in front of a string is therefor not missing
self.portal.doc1.title = 'Kölle Alaaf' # What is "Fasching"?
@ -92,8 +93,10 @@ class TestUserNotificationUnit(unittest.TestCase):
def test_do_not_notify_user_when_notification_is_disabled(self):
registry = queryUtility(IRegistry)
registry['plone.app.discussion.interfaces.IDiscussionSettings.' +
'user_notification_enabled'] = False
registry[
'plone.app.discussion.interfaces.IDiscussionSettings.' +
'user_notification_enabled'
] = False
comment = createObject('plone.Comment')
comment.text = 'Comment text'
comment.user_notification = True
@ -121,7 +124,9 @@ class TestUserNotificationUnit(unittest.TestCase):
def test_do_not_notify_user_when_no_sender_is_available(self):
# Set sender mail address to none and make sure no email is send to
# the moderator.
self.portal.email_from_address = None
registry = getUtility(IRegistry)
mail_settings = registry.forInterface(IMailSchema, prefix='plone')
mail_settings.email_from_address = None
comment = createObject('plone.Comment')
comment.text = 'Comment text'
comment.user_notification = True
@ -131,7 +136,6 @@ class TestUserNotificationUnit(unittest.TestCase):
comment.text = 'Comment text'
self.conversation.addComment(comment)
self.assertEqual(len(self.mailhost.messages), 0)
def test_notify_only_once(self):
@ -171,20 +175,22 @@ class TestModeratorNotificationUnit(unittest.TestCase):
sm.unregisterUtility(provided=IMailHost)
sm.registerUtility(mailhost, provided=IMailHost)
# We need to fake a valid mail setup
self.portal.email_from_address = "portal@plone.test"
registry = getUtility(IRegistry)
mail_settings = registry.forInterface(IMailSchema, prefix='plone')
mail_settings.email_from_address = "portal@plone.test"
self.mailhost = self.portal.MailHost
# Enable comment moderation
self.portal.portal_types['Document'].allow_discussion = True
self.portal.portal_workflow.setChainForPortalTypes(
('Discussion Item',),
('comment_review_workflow',))
('comment_review_workflow',)
)
# Enable moderator notification setting
registry = queryUtility(IRegistry)
registry['plone.app.discussion.interfaces.IDiscussionSettings.' +
'moderator_notification_enabled'] = True
# Create test content
self.portal.invokeFactory('Document', 'doc1')
self.portal_discussion = self.portal.portal_discussion
registry[
'plone.app.discussion.interfaces.IDiscussionSettings.' +
'moderator_notification_enabled'
] = True
# Archetypes content types store data as utf-8 encoded strings
# The missing u in front of a string is therefor not missing
self.portal.doc1.title = 'Kölle Alaaf' # What is "Fasching"?
@ -252,7 +258,9 @@ class TestModeratorNotificationUnit(unittest.TestCase):
def test_do_not_notify_moderator_when_no_sender_is_available(self):
# Set sender mail address to nonw and make sure no email is send to the
# moderator.
self.portal.email_from_address = None
registry = getUtility(IRegistry)
mail_settings = registry.forInterface(IMailSchema, prefix='plone')
mail_settings.email_from_address = None
comment = createObject('plone.Comment')
comment.text = 'Comment text'
@ -272,7 +280,3 @@ class TestModeratorNotificationUnit(unittest.TestCase):
self.conversation.addComment(comment)
self.assertEqual(len(self.mailhost.messages), 0)
def test_suite():
return unittest.defaultTestLoader.loadTestsFromName(__name__)

View File

@ -0,0 +1,27 @@
from plone.app.discussion.testing import PLONE_APP_DISCUSSION_ROBOT_TESTING
from plone.app.testing import ROBOT_TEST_LEVEL
from plone.testing import layered
import os
import unittest
import robotsuite
def test_suite():
suite = unittest.TestSuite()
current_dir = os.path.abspath(os.path.dirname(__file__))
robot_dir = os.path.join(current_dir, 'robot')
robot_tests = [
os.path.join('robot', doc) for doc in
os.listdir(robot_dir) if doc.endswith('.robot') and
doc.startswith('test_')
]
for robot_test in robot_tests:
robottestsuite = robotsuite.RobotTestSuite(robot_test)
robottestsuite.level = ROBOT_TEST_LEVEL
suite.addTests([
layered(
robottestsuite,
layer=PLONE_APP_DISCUSSION_ROBOT_TESTING
),
])
return suite

View File

@ -1,54 +0,0 @@
import unittest2 as unittest
from zope.component import queryUtility, createObject
from plone.app.testing import TEST_USER_ID, setRoles
from plone.app.discussion.testing import \
PLONE_APP_DISCUSSION_INTEGRATION_TESTING
from plone.app.discussion.interfaces import ICommentingTool, IConversation
class ToolTest(unittest.TestCase):
layer = PLONE_APP_DISCUSSION_INTEGRATION_TESTING
def setUp(self):
self.portal = self.layer['portal']
setRoles(self.portal, TEST_USER_ID, ['Manager'])
self.portal.invokeFactory(id='doc1',
title='Document 1',
type_name='Document')
def test_tool_indexing(self):
# Create a conversation. In this case we doesn't assign it to an
# object, as we just want to check the Conversation object API.
conversation = IConversation(self.portal.doc1)
# Add a comment.
comment = createObject('plone.Comment')
comment.creator = 'jim'
comment.author_name = "Jim"
comment.text = 'Comment text'
conversation.addComment(comment)
# Check that the comment got indexed in the tool:
tool = queryUtility(ICommentingTool)
comment = list(tool.searchResults())
self.assertTrue(len(comment) == 1,
"There is only one comment, but we got"
" %s results in the search" % len(comment))
self.assertEqual(comment[0].Title, 'Jim on Document 1')
def test_unindexing(self):
pass
def test_search(self):
# search returns only comments
pass
def test_suite():
return unittest.defaultTestLoader.loadTestsFromName(__name__)

View File

@ -32,7 +32,6 @@ class WorkflowSetupTest(unittest.TestCase):
self.portal.invokeFactory('Folder', 'test-folder')
self.folder = self.portal['test-folder']
self.portal.portal_types['Document'].allow_discussion = True
self.portal_discussion = self.portal.portal_discussion
self.folder.invokeFactory('Document', 'doc1')
self.doc = self.folder.doc1
@ -47,9 +46,12 @@ class WorkflowSetupTest(unittest.TestCase):
def test_default_workflow(self):
"""Make sure one_state_workflow is the default workflow.
"""
self.assertEqual(('one_state_workflow',),
self.assertEqual(
('one_state_workflow',),
self.portal.portal_workflow.getChainForPortalType(
'Discussion Item'))
'Discussion Item'
)
)
def test_review_comments_permission(self):
#'Review comments' in self.portal.permissionsOfRole('Admin')
@ -58,8 +60,13 @@ class WorkflowSetupTest(unittest.TestCase):
self.assertTrue(self.portal.portal_membership.checkPermission(
'Review comments', self.folder), self.folder)
setRoles(self.portal, TEST_USER_ID, ['Member'])
self.assertFalse(self.portal.portal_membership.checkPermission(
'Review comments', self.folder), self.folder)
self.assertFalse(
self.portal.portal_membership.checkPermission(
'Review comments',
self.folder
),
self.folder
)
def test_reply_to_item_permission(self):
pass
@ -121,8 +128,9 @@ class CommentOneStateWorkflowTest(unittest.TestCase):
comment.text = 'Comment text'
cid = conversation.addComment(comment)
self.comment = self.folder.doc1.restrictedTraverse(\
'++conversation++default/%s' % cid)
self.comment = self.folder.doc1.restrictedTraverse(
'++conversation++default/%s' % cid
)
self.portal.acl_users._doAddUser('member', 'secret', ['Member'], [])
self.portal.acl_users._doAddUser(
@ -179,10 +187,6 @@ class CommentReviewWorkflowTest(unittest.TestCase):
('Discussion Item',),
('comment_review_workflow',))
# Create a Document
self.portal.invokeFactory('Document', 'doc1')
self.portal_discussion = self.portal.portal_discussion
# Create a conversation for this Document
conversation = IConversation(self.portal.doc1)
@ -228,26 +232,42 @@ class CommentReviewWorkflowTest(unittest.TestCase):
def test_publish(self):
self.portal.REQUEST.form['comment_id'] = self.comment_id
self.portal.REQUEST.form['workflow_action'] = 'publish'
self.assertEqual('pending',
self.assertEqual(
'pending',
self.portal.portal_workflow.getInfoFor(
self.comment, 'review_state'))
self.comment,
'review_state'
)
)
view = self.comment.restrictedTraverse('@@moderate-publish-comment')
view()
self.assertEqual('published', self.portal.portal_workflow.\
getInfoFor(self.comment, 'review_state'))
self.assertEqual(
'published',
self.portal.portal_workflow.getInfoFor(
self.comment,
'review_state'
)
)
def test_publish_as_anonymous(self):
logout()
self.portal.REQUEST.form['comment_id'] = self.comment_id
self.portal.REQUEST.form['workflow_action'] = 'publish'
self.assertEqual('pending', self.portal.portal_workflow.\
getInfoFor(self.comment, 'review_state'))
self.assertRaises(Unauthorized,
self.assertEqual(
'pending', self.portal.portal_workflow.getInfoFor(
self.comment,
'review_state'
)
)
self.assertRaises(
Unauthorized,
self.comment.restrictedTraverse,
'@@moderate-publish-comment')
self.assertEqual('pending', self.portal.portal_workflow.\
getInfoFor(self.comment, 'review_state'))
def test_suite():
return unittest.defaultTestLoader.loadTestsFromName(__name__)
'@@moderate-publish-comment'
)
self.assertEqual(
'pending',
self.portal.portal_workflow.getInfoFor(
self.comment,
'review_state'
)
)

View File

@ -2,7 +2,13 @@ from zope.component import getUtility
from plone.registry.interfaces import IRegistry
from plone.app.discussion.interfaces import IDiscussionSettings
default_profile = 'profile-plone.app.discussion:default'
def update_registry(context):
registry = getUtility(IRegistry)
registry.registerInterface(IDiscussionSettings)
def update_rolemap(context):
context.runImportStepFromProfile(default_profile, 'rolemap')

View File

@ -6,28 +6,28 @@ from plone.app.discussion.interfaces import _
HAS_CAPTCHA = False
try:
import plone.formwidget.captcha
import plone.formwidget.captcha # noqa
HAS_CAPTCHA = True # pragma: no cover
except ImportError:
pass
HAS_RECAPTCHA = False
try:
import plone.formwidget.recaptcha
import plone.formwidget.recaptcha # noqa
HAS_RECAPTCHA = True # pragma: no cover
except ImportError:
pass
HAS_AKISMET = False
try:
import collective.akismet
import collective.akismet # noqa
HAS_AKISMET = True # pragma: no cover
except ImportError:
pass
HAS_NOROBOTS = False
try:
import collective.z3cform.norobots
import collective.z3cform.norobots # noqa
HAS_NOROBOTS = True # pragma: no cover
except ImportError:
pass

View File

@ -5,3 +5,4 @@ all_files = 1
[upload_sphinx]
upload-dir = docs/html

View File

@ -1,6 +1,7 @@
from setuptools import setup, find_packages
from setuptools import find_packages
from setuptools import setup
version = '2.2.1.dev0'
version = '2.4.2.dev0'
install_requires = [
'setuptools',
@ -22,13 +23,13 @@ install_requires = [
'zope.lifecycleevent',
'zope.site',
'z3c.form>=2.3.3',
]
]
setup(name='plone.app.discussion',
version=version,
description="Enhanced discussion support for Plone",
long_description=open("README.rst").read() + "\n" +
open("CHANGES.txt").read(),
open("CHANGES.rst").read(),
classifiers=[
"Framework :: Plone",
"Framework :: Plone :: 3.3",
@ -51,7 +52,11 @@ setup(name='plone.app.discussion',
extras_require={
'test': [
'plone.app.testing',
'interlude',
'plone.stringinterp',
'plone.contentrules',
'plone.app.contentrules',
'plone.app.contenttypes[test]',
'plone.app.robotframework[ride,reload]',
]
},
entry_points="""
@ -59,3 +64,4 @@ setup(name='plone.app.discussion',
target = plone
""",
)

21
travis.cfg Normal file
View File

@ -0,0 +1,21 @@
[buildout]
extends = buildout.cfg
parts +=
download
install
code-analysis
eggs-directory = buildout-cache/eggs
download-cache = buildout-cache/downloads
[download]
recipe = hexagonit.recipe.download
url = https://launchpad.net/plone/4.3/4.3.4/+download/Plone-4.3.4-UnifiedInstaller.tgz
[install]
recipe = collective.recipe.cmd
on_install = true
cmds = tar jxvf ${download:location}/Plone-4.3.4-UnifiedInstaller/packages/buildout-cache.tar.bz2 1>/dev/null
[code-analysis]
recipe = plone.recipe.codeanalysis
return-status-codes = True